最近开发在解决Api接口超时问题时,发现我们的网关重试机制没有生效,网关配置如下:
spring: cloud: loadbalancer: retry: enabled: true ribbon: ConnectTimeout: 1000 ReadTimeout: 1000 MaxAutoRetries: 0 MaxAutoRetriesNextServer: 1 OkToRetryOnAllOperations: false hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 4000 zuul: ignored-services: '*' semaphore: max-semaphores: 500 routes: blog_atang: path: /atang/** serviceId: blog-atang sensitiveHeaders: "*"
我听到没生效也比较诧异,因为参数都是正确的,至少实际使用过程中已经证明超时参数已经生效了,然而和开发再次一起测试,果然没有触发重试。又网上查了一些资料,总结网上的各种文档一共有3个重试开关和一种重试策略。
第一个开关:ribbon.restclient.enabled=true ,这个不知道是不是SpringBoot版本的问题,我们加了以后也没有触发重试(我们的版本是SpringCloud Edgware.SR6,SpringBoot 1.5.22),但网上有篇文章使用的SpringCloud Greenwich.SR2,SpringBoot 2.1.3.RELEASE,开启以后可以正常重试。
第二个开关:spring.cloud.loadbalancer.retry.enabled=true,有文章说这个参数可以开启重试机制(默认值为false),但实际上我们默认就配置为true了,为了测试这个参数的效果,改成false以后,接口直接无法访问了,此次问题主要是解决重试,所以就没有去查看源码深入研究此参数了。
第三个开关:zuul.retryable=true,这个开关需要引入spring-retry依赖才能使用:
<dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency>
但是很多文章虽然说了要引入此依赖,但是并没有说配置zuul.retryable=true(默认为false),所以即使引入了依赖,超时路由也不会重试。
还支持只开启指定路由重试,配置为:zuul.routes.<routename>.retryable=true。
还有一种重试方案就是采用ribbon的重试策略,配置为:ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RetryRule,实际测试并没有触发重试。关于Ribbon的负载均衡策略,可以参考如下介绍:
1、BestAvailabl
选择一个最小的并发请求的 Server,逐个考察 Server,如果 Server 被标记为错误,则跳过,然后再选择 ActiveRequestCount 中最小的 Server。
2、AvailabilityFilteringRule
过滤掉那些一直连接失败的且被标记为 circuit tripped 的后端 Server,并过滤掉那些高并发的后端 Server 或者使用一个 AvailabilityPredicate 来包含过滤 Server 的逻辑。其实就是检查 Status 里记录的各个 Server 的运行状态。
3、ZoneAvoidanceRule
使用 ZoneAvoidancePredicate 和 AvailabilityPredicate 来判断是否选择某个 Server,前一个判断判定一个 Zone 的运行性能是否可用,剔除不可用的 Zone(的所有 Server),AvailabilityPredicate 用于过滤掉连接数过多的 Server。
4、RandomRule
随机选择一个 Server。
5、RoundRobinRule
轮询选择(默认策略),轮询 index,选择 index 对应位置的 Server。
6、RetryRule
对选定的负载均衡策略机上重试机制,也就是说当选定了某个策略进行请求负载时在一个配置时间段内若选择 Server 不成功,则一直尝试使用 subRule 的方式选择一个可用的 Server。
7、ResponseTimeWeightedRule
作用同 WeightedResponseTimeRule,ResponseTime-Weighted Rule 后来改名为 WeightedResponseTimeRule。
8、WeightedResponseTimeRule
根据响应时间分配一个 Weight(权重),响应时间越长,Weight 越小,被选中的可能性越低。
总结,SpringCloud 版本为Edgware.x,SpringBoot 版本为1.5.x时,需要引入spring-retry,然后配置文件里面配置zuul.retryable=true,ribbon的重试参数才会生效。至于SpringBoot 2.x版本,按照网上有些文档说明设置ribbon.restclient.enabled=true就会开启重试,这个有待实测。经过此次问题,更加说明了不能太相信网上的文档,而且搜索出来的文档质量越来越差了,千篇一律;大多数情况只要有一篇原创发布,过几天就会有很多相似的文档就出来了,大部分是平台采集,加上没有实际测试的复制粘贴。所以阿汤博客运维文档和其他技术文档都是经过实际测试或者亲身经历的问题总结,如果有不全面的地方,可以留言讨论。原创不易,复制请注明出处,谢谢。