SpringCloud Feign重试不生效问题排查

2020年9月28日16:22:07 发表评论 4,450 ℃

Feign重试不生效问题的发现,主要还是因为上篇文章《SpringCloud Zuul(Ribbon)重试配置不生效解决办法》里面介绍的原因。当我解决了Zuul重试不生效的问题,测试发现只有如下场景:zuul-->访问A1、A2,A服务返回超时,也就是说Api接口的第一级跨度超过zuul配置ribbon.ReadTimeout的值才会触发ribbon重试。场景一如下图:

SpringCloud Feign重试不生效问题排查

场景二如下图,Api接口跨度多个服务的调用:

SpringCloud Feign重试不生效问题排查

此时ReadTimeout有两种情况:

1、Zuul网关的ribbon.ReadTimeout>服务端feign.client.config.default.readTimeout。

比如:Zuul网关的ribbon.ReadTimeout=3000,服务端配置的feign.client.config.default.readTimeout=1000,当请求从Zuul网关进来,负载均衡到任意的A服务节点,比如A1,此时A1通过feign调用B服务和C服务的任意节点,比如B2和C1。此时分两种情况:

a.当A1并发请求B2和C1,此时如果有一个接口超时,或者两个接口都超时,那么ReadTime都是1s左右,而并没有达到ribbon.ReadTimeout=3000,所以不会触发网关的ribbon重试,所以此时接口没有返回正常的结果。

b.当A1顺序请求B2和C1,此时如果有一个接口超时,那么ReadTime为1s左右,如果是两个接口都超时,那么ReadTime都是2s左右,而并没有达到ribbon.ReadTimeout=3000,所以不会触发网关的ribbon重试,所以此时接口没有返回正常的结果。

所以只要A服务处理请求的时间没有超过在Zuul配置ribbon.ReadTimeout的值,那么都不会触发ribbon的重试。

2、Zuul网关的ribbon.ReadTimeout=服务端feign.client.config.default.readTimeout。

比如:Zuul网关的ribbon.ReadTimeout=1000,服务端配置的feign.client.config.default.readTimeout=1000,当请求从Zuul网关进来,负载均衡到任意的A服务节点,比如A2,此时A2通过feign调用B服务和C服务的任意节点,比如B1和C2。此时不管是调用B1或者C2超时,或者都超时,那么都会触发Zuul网关的ribbon重试,重试次数主要由ribbon.MaxAutoRetries和ribbon.MaxAutoRetriesNextServer配置的值决定。

比如ribbon.MaxAutoRetries=0,ribbon.MaxAutoRetriesNextServer=1那么,Zuul会根据配置,重新调用A1进行重试,而A1也是通过feign调随机用B服务和C服务的任意节点。

总结以上两种情况,A服务调用调用B服务或者C服务任意节点超时,A服务都不会对B服务和C服务的当前或者其他节点进行重试。

那么怎么样,才能让服务A调用服务B超时的时候,进行重试呢?网上找了些资料,总结如下:

1、Feign组件默认使用Ribbon的重试机制并增加了根据状态码判断重试机制,默认情况下是不启用的。

2、Feign使用的是Spring Retry组件,需要引入依赖才能启用,也就是网关ribbon重试那个组件。

  <dependency>
     <groupId>org.springframework.retry</groupId>
     <artifactId>spring-retry</artifactId>
 </dependency>

3、引入以后没有正确配置ribbon,默认同一节点会重试5次,即使第一次访问就触发了Zuul网关已经返回超时,并且浏览器已经返回超时结果,Feign也会重试5次,如果刚好网关又触发了重试,重试次数配置得也比较大的话,那么就会产生大量多余的请求,会对系统和服务性能造成一定的影响,哪怕没有触发网关的重试,出现一个节点某个服务故障的时候,也会产生多余的性能开销。

4、根据网上找的资料服务端ribbon正确配置如下:

${spring.application.name}:  
  ribbon:
    MaxAutoRetries: 1
    MaxAutoRetriesNextServer: 1 
    OkToRetryOnAllOperations: false
    NFLoadBalancerRuleClassName: AvailabilityFilteringRule
feign:
  client:
    config:
      default:
        connectTimeout: 1000
        readTimeout: 1000

OkToRetryOnAllOperations建议不要设置为true,即使接口做了幂等,避免后续哪个接口忘记做幂等产生脏数据。

通过实际的测试,发现接入依赖以后,Feign的请求超时的确会触发重试,但是实际上网关的ribbon.ReadTimeout、ribbon.MaxAutoRetries、ribbon.MaxAutoRetriesNextServer这些参数都会影响Feign的重试可能性和结果,下篇文章《SpringCloud Ribbon和Feign重试参数性能实测对比》详细介绍实际测试结果。

【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: