- 问题:
在zuul中想要开启客户端负载均衡的重试机制,网上有很多文章介绍,但是我尝试一下他们提供的配置,发现不起作用。后来通过仔细查找网上别人的文章,最终成功开启重试,记录下来,希望可以帮到别人少做弯路。 - 环境:
- Spring Cloud: Hoxton.SR7
- Spring boot: 2.3.3.RELEASE
- 解决方法:
- 在pom.xml文件中引入
spring-retry
包。这是zuul重试机制必须依赖的一个包,但很多文章没有提及。
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
- 配置zuul的application.yml
zuul:
##注意,这里必须开启
#开启重试,
retryable: true
#使用线程池做隔离,默认是信号量SEMAPHORE(信号量)
ribbon-isolation-strategy: thread
thread-pool:
#为不同的路由使用不同的线程池
use-separate-thread-pools: true
#线程名称前缀
thread-pool-key-prefix: zuulgw
##针对服务实例的超时和重试策略
hello-world: #服务实例的名称,也有是服务里的yml文件中spring.applicaiton.name的设置。
ribbon:
#ribbon请求连接的超时时间
ConnectTimeout: 1000
#请求处理的超时时间
ReadTimeout: 1000
#对所有请求操作都进行重试。设置为false,表示只会对get请求进行重试
OkToRetryOnAllOperations: true
#对服务实例的重试次数(除去首次访问外)。默认值为0,如果不设置,则只会有首次访问,不会有重试
MaxAutoRetries: 1
#切换到另一个实例的次数。默认值为1,如果不设置,会有一次切换
MaxAutoRetriesNextServer: 1
##全局超时和重试策略
ribbon:
#建立连接的超时时间
ConnectTimeout: 1000
#请求处理的超时时间
ReadTimeout: 1000
#对所有请求操作都进行重试。设置为false,表示只会对get请求进行重试
OkToRetryOnAllOperations: true
#对服务实例的重试次数(除去首次访问外)。如果不设置,则只会有首次访问,不会有重试
MaxAutoRetries: 1
#切换到另一个实例的次数。如果不设置,会有一次切换
MaxAutoRetriesNextServer: 1
hystrix:
command:
default:
execution:
#启用超时时间
timeout:
enabled: true
isolation:
thread:
#Hystrix断路器的超时时间,设置时间需要超过上面ribbon的连接过期时间,加上重试的时间
timeoutInMilliseconds: 8500
- 几点提醒:
a. 想要开启重试机制,必须引入spring-retry
包和配置applicaiton.yml
中的zuul.retryable=true
,两者缺一不可。
b. 注意application.yml
中的两个配置:
-MaxAutoRetries
: 表示对服务实例的重试次数(除去首次访问外)。默认为0,表示只会有首次访问,不会有重试
-MaxAutoRetriesNextServer
:切换到另一个另一个实例的次数。默认为1,表示会有一次切换
比如设置:MaxAutoRetries=1
,MaxAutoRetriesNextServer=1
, 则表示先对第一个服务实例发起请求(请求1),超时后重试(请求2),再超时,会换一个服务实例,再发起一个请求(请求3),如果超时,会再重试一次(请求4),这样对两个服务实例,总共发起了4次请求。
c. 注意hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds
hystrix超时的设置。这个值不能设置过小,否则会发生hystrix timeout熔断,fallback信息返回,但是zuul的重试仍然正在进行中。这个值得设置有一个公式,如下。hystrix.timeoutInMilliseconds >= ribbonTimeout = (ribbonReadTimeout + ribbonConnectTimeout) * (maxAutoRetries + 1) * (maxAutoRetriesNextServer + 1)
d. 另外,如果不引入spring-retry
包,也能开启重试机制,需要在applicatin.yml
中设置ribbon.restclient.enabled=true
(zuul.retryable=true
仍然需要设置)。它会使用ribbon中的RestClient去替代zuul中的HttpClient去实现http连接。但是,按照官方文档的说法,它有一个缺陷,不支持HTTP的PATCH方法请求。所以不推荐这么设置。
- 参考文章:
具体的实现机制,请参考下面这篇文章,作者从源码的角度分析了zuul重试机制,并在文章最后面给出了结论。
http://blog.didispace.com/spring-cloud-zuul-retry-detail/