Spring Cloud Ribbon
主要功能是在微服务中做负载均衡和重试(提供容错机制)(配合Eureka使用)
nginx是前端到后端的负载均衡,而Ribbon做的是后台Provider之间的负载均衡
同样的,Ribbon也可以做redis缓存,在得到数据的时候,可以通过Redis判断是否有缓存,如果有缓存,直接读取缓存,如果没有缓存,再通过Ribbon获取其他Provider的结果,并保存到缓存中,最后返回
Ribbon是封装了RestTemplate,并且做了代码增强
负载均衡
1.先从eureka获取服务的主机地址列表
2.对主机地址列表,轮询发送请求(是主机服务名,而不是url地址)
3.配置
3.1 对RestTemplate添加@LoadBalanced注解
@SpringBootApplication
public class Sp06RibbonApplication {
public static void main(String[] args) {
SpringApplication.run(Sp06RibbonApplication.class, args);
}
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
3.2 请求地址从url变更为eureka中注册的服务名,这样可以通过一个服务名连接到多个地址
服务名就是在yml配置中的spring.application.name: item-service
重试
再Eureka中注册的服务中,如果同一个服务名有多台服务器,当访问一台服务器失败之后,会访问同个服务名下的另外的服务器
参数:
MaxAutoRetries:单台服务器重试次数
MaxAutoRetriesNextServer:更换服务器的次数
OkToRetryOnAllOperations:是否对所有配型请求都重试,默认只对get请求重试
ConnectTimeout:建立连接通道超时时间
ReadTimeout:成功建立连接发送请求之后,等待响应的超时连接
前三个参数在yml中配置,最后两个超时时间需要在java代码中配置
举例:
MaxAutoRetries: 1
MaxAutoRetriesNextServer:2
说明:如果同服务名下有2台A和B,当A连接失败后,会再重试一次(共连接2次)
当A两次连接都失败后,会连接B,同样尝试两次连接,如果一样失败,还会回到A再连接
当此次A连接失败后,不会在尝试连接
配置:
添加SpringRetry依赖(需要单独添加依赖)
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
yml配置:
ribbon:
MaxAutoRetries: 1
MaxAutoRetriesNextServer: 2
OkToRetryOnAllOperations: false
这里的配置会有黄线,不用管
配置类:
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
/**
* ConnectTimeout
* ReadTimeout
* 不能再yml中配置,而是需要再java代码中配置
*/
SimpleClientHttpRequestFactory f = new SimpleClientHttpRequestFactory();
f.setConnectTimeout(1000);
f.setReadTimeout(1000);
return new RestTemplate();
}
测试Demo
@GetMapping("/{orderId}")
public JsonResult<List<Item>> getItems(@PathVariable String orderId) throws Exception{
log.info("orderId= "+orderId+", port= "+port);
//60%的概率执行延迟
if(Math.random()<0.6) {
int t = new Random().nextInt(5000);
log.info("延迟时间:"+t);
Thread.sleep(t);
}
List<Item> items = itemService.getItems(orderId);
return JsonResult.ok(items).msg("port: "+port);
}
在Provider的Controller中加入一个延迟计划,睡眠时间可以改成一个固定值,按照上面的配置,只要超过1秒,就会进行重试