一.开启负载均衡
Eureka中已经集成了Ribbon,所以我们无需引入新的依赖
在RestTemplate的配置方法上添加@LoadBalanced
注解,默认就是轮询方式的负载均衡
//如果赋予了restTemplate负载均衡的能力 就只能通过服务名去调了
@Bean
@LoadBalanced //赋予负载均衡的能力,默认是轮询
RestTemplate restTemplate(){
return new RestTemplate();
}
这里需要注意,一旦RestTemplate上打上@LoadBalanced标签,说明已经赋予了负载均衡的能力,就不能使用 ip+端口的方式来发送请求了,
就只能通过服务名去调用了!
此时我们复制一份provider,修改为provider2,修改其配置文件application.yml,修改其端口,服务名不变
server:
port: 8084
spring:
application:
name: provider
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8080/eureka
修改其controller
@RestController
public class ProviderController {
@RequestMapping("/provider")
public String providerTest(@RequestParam(value = "name") String name){
return "你好,这里是另外一个provider";
}
}
然后启动,访问localhost:8083/comsumer/name=andy, 多次刷新交替出现 andy你好,这里是provider,andy你好,这里另外一个是provider,那么负载均衡成功!
二.负载均衡策略
这里只提供一种负载均衡算法-配置方式
使用配置方式定义负载均衡规则更为简单,且优先于编码方式 , SpringBoot也帮我们提供了修改负载均衡规则的配置入口:
PROVIDER:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #随机算法
再次测试,发现结果变成了随机:
三.重试机制
现在有一个问题,如果一个负载均衡的服务关闭了,但是Eureka注册中心此时并未执行剔除定时任务,当counsumer调用服务时正好选中了这个关闭的服务,怎么办?我们肯定希望如果这个服务调不通,再去尝试调另一个,而不是直接失败超时!
而Ribbon中也有相应的重试机制,Spring Cloud 整合了Spring Retry 来增强RestTemplate的重试能力,当一次服务调用失败后,不会立即抛出一次,而是再次重试另一个服务。
spring:
cloud:
loadbalancer:
retry:
enabled: true # 开启Spring Cloud的重试功能
PROVIDER:
ribbon:
ConnectTimeout: 250 # Ribbon的连接超时时间
ReadTimeout: 1000 # Ribbon的数据读取超时时间
OkToRetryOnAllOperations: true # 是否对所有操作都进行重试
MaxAutoRetriesNextServer: 1 # 切换实例的重试次数
MaxAutoRetries: 1 # 对当前实例的重试次数
根据如上配置,当访问到某个服务超时后,它会再次尝试访问下一个服务实例,如果不行就再换一个实例,如果不行,则返回失败。切换次数取决于MaxAutoRetriesNextServer
参数的值
引入spring-retry依赖
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
我们重启consumer,测试,发现即使provider2宕机,也能通过另一台服务实例获取到结果!