父工程pom.xml
<dependencyManagement>
<dependencies>
<!-- 1.Spring Cloud Hoxton.SR3 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 2.Spring Cloud Alibaba
新版本的groupId = com.alibaba.cloud
旧版本的groupId = org.springframework.cloud
-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Nacos 服务注册 - Nacos Discovery
作用:解决模块之间的调用问题
github:https://github.com/alibaba/nacos
官网:https://nacos.io/zh-cn/
pom.xml
<!-- 新增 nacos discovery -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
yml文件
# 指定nacos地址 (相当于淘宝地址)
spring:
cloud:
nacos:
discovery:
server-addr: localhost:8848
启动器
@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class,args);
}
}
负载均衡
RestTemplate
consumer - config
@Configuration
public class ConsumerConfig {
@Bean
@LoadBalanced // 负载均衡
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
consumer - controller
@RestController
@RequestMapping("consumer")
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
// 调用提供者的方法
@GetMapping("port")
public String getProviderPort() {
String result = "";
// 获取provider的实例
List<ServiceInstance> providerList = discoveryClient.getInstances("provider");
// 自己写一个简陋的随机的算法
// 随机数的种子为集合的长度,不能超过
int i = ThreadLocalRandom.current().nextInt(providerList.size());
// 随机获取实例
ServiceInstance provider = providerList.get(i);
// 进行url拼接 uri=统一资源定位符(ip + 端口号) url = uri + 映射
String url = provider.getUri() + "/provider/port";
// 发送url获取返回值
result = restTemplate.getForObject(url, String.class);
return result;
}
}
Ribbon
consumer - config
@Configuration
public class ConsumerConfig {
@Bean
@LoadBalanced // 负载均衡
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
consumer - controller
@RestController
@RequestMapping("consumer")
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("port")
public String getPort(){
return restTemplate.getForObject("http://provider/provider/port",String.class);
}
}
负载均衡策略
provider:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
负载均衡策略 | 描述 |
---|---|
RoundRobinRule:轮询策略 | 默认超过10次获取到的server都不可用,会返回一个空的server |
RandomRule:随机策略 | 如果随机到的server为null或者不可用的话,会while不停的循环选取 |
RetryRule:重试策略 | 一定时限内循环重试。默认继承RoundRobinRule,也支持自定义注入,RetryRule会在每次选取之后,对选举的server进行判断,是否为null,是否alive,并且在500ms内会不停的选取判断。而RoundRobinRule失效的策略是超过10次,RandomRule是没有失效时间的概念,只要serverList没都挂。 |
BestAvailableRule:最小连接数策略 | 遍历serverList,选取出可用的且连接数最小的一个server。该算法里面有一个LoadBalancerStats的成员变量,会存储所有server的运行状况和连接数。如果选取到的server为null,那么会调用RoundRobinRule重新选取。 |
AvailabilityFilteringRule:可用过滤策略 | 扩展了轮询策略,会先通过默认的轮询选取一个server,再去判断该server是否超时可用,当前连接数是否超限,都成功再返回。 |
ZoneAvoidanceRule:区域权衡策略**(默认策略)** | 扩展了轮询策略,继承了2个过滤器:ZoneAvoidancePredicate和AvailabilityPredicate,除了过滤超时和链接数过多的server,还会过滤掉不符合要求的zone区域里面的所有节点, 在一个区域/机房内的服务实例中轮询。先过滤再轮询 |
响应时间权重 |
权重
- 创建NacosWeightedRule
- 修改NFLoadBalancerRuleClassName: cn.qf.consumer.config.NacosWeightedRule
@Slf4j
public class NacosWeightedRule extends AbstractLoadBalancerRule {
@Autowired
private NacosDiscoveryProperties nacosDiscoveryProperties;
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
//读取配置文件
}
@Override
public Server choose(Object o) {
ILoadBalancer loadBalancer = this.getLoadBalancer();
BaseLoadBalancer baseLoadBalancer = (BaseLoadBalancer) loadBalancer;
//获取要请求的微服务名称
String name = baseLoadBalancer.getName();
//获取服务发现的相关API
NamingService namingService = nacosDiscoveryProperties.namingServiceInstance();
try {
Instance instance = namingService.selectOneHealthyInstance(name);
log.info("选择的实例是port={},instance={}", instance.getPort(), instance);
return new NacosServer(instance);
} catch (NacosException e) {
e.printStackTrace();
return null;
}
}
}
provider:
ribbon:
NFLoadBalancerRuleClassName: cn.qf.consumer.config.NacosWeightedRule
openFeign
- Feign是Springcloud组件中的一个轻量级Restful的HTTP服务客户端,Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务
- Feign的使用方式是:使用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务
- OpenFeign是springcloud在Feign的基础上支持了SpringMVC的注解,如@RequestMapping等等
- OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务
pom.xml
<!--openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
consumer - 创建包跟接口
@FeignClient("provider") // 生产者ID(name)
public interface ProviderFeignService {
// 如果provider的controller有请求窄化必须添加
@GetMapping("provider/port")
String getPort();
}
----------------以下为provicer的controller,仅仅用于给上面的接口进行对比----------------
@GetMapping("port")
public String getPort() {
return this.port;
}
consumer - controller
@GetMapping("openFeign")
public String port() {
return providerFeignService.getPort();
}