问题描述
在使用Ribbon、Feign、Hystrix组合时,因为配置的问题出现以下现象,让我的大脑CPU烧的不行不行(拿我老家话说就是“脑子ran滴奥”)。
重试次数不生效
使用以下配置时fegin调用超时重试次数一直是3次,共调用了4次。(后面发现是我对配置理解有问题)
# 连接超时时间
ribbon.ConnectTimeout=1000
# 响应超时时间
ribbon.ReadTimeout=3000
# 同一服务器上的最大重试次数(不包括首次尝试)
ribbon.MaxAutoRetries=1
# 要重试的下一个服务器的最大数量(不包括第一个服务器)
ribbon.MaxAutoRetriesNextServer=1
# 是否所有操作都重试,默认在get请求下会重试,其他情况不会重试
同时在被调用的服务中睡眠了5秒,达到超时效果。
开启熔断后重试次数生效
feign开启熔断后,后台日志打印共调用服务2次,然后回退降级了。配置如下:
# 开启fegin熔断
feign.hystrix.enabled=true
# hystrix的超时时间
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=6000
fallbackFactory回退降级异常为空
feign使用fallbackFactory回退方式捕捉异常时,无论超时、服务不存在、业务异常等原因,异常信息总是为null。
问题1分析
针对重试次数不生效问题是这样的,刚开始我认为的MaxAutoRetries和MaxAutoRetriesNextServer都配置为1,重试次数为1次,一共请求2次。
其实当MaxAutoRetriesNextServer为1时,请求超时或失败后不论有几个实例都会切换一次,也就是说即使只有1个实例,也会切换到自己,然后再去请求,所以就出现了重试次数为3次的现象(第一次超时重试+切换实例请求+切换实例超时重试)。
所以Ribbon请求最多会被执行(1 + maxAutoRetries ) * (1 + MaxAutoRetriesNextServer)次。
问题2、3分析
问题1了解后,问题2、3也就清晰可见了。
首先要知道feign默认支持Ribbon,二者的重试机制有冲突,所以源码关闭了feign的重试机制,使用Ribbon的重试机制。
其次Hystrix是在feign的基础上调用后进行熔断降级操作,所以Hystrix的超时时间要大于feign调用的总超时时间,也就是ribbon的总超时时间,否则重试机制就没有任何意义。
所以在对问题1理解有误时,问题2“开启熔断后重试次数生效”这个事我就很费解。 现在看来,原来是hystrix的超时时间到了,对调用依赖进行了熔断降级。
问题3“fallbackFactory回退降级异常为空”也是因为hystrix的超时时间先到,而调用还没给响应,没有捕捉到真正的异常信息。
当把Hystrix的超时时间设置为(1 + maxAutoRetries ) * (1 + MaxAutoRetriesNextServer)✖️ReadTimeout时,问题2、3也就解释的通了。
总结
feign请求次数计算
feign的总请求次数=(1 + maxAutoRetries ) * (1 + MaxAutoRetriesNextServer)
Hystrix超时时间设置公式
Hystrix超时时间=(1 + maxAutoRetries ) * (1 + MaxAutoRetriesNextServer)✖️ReadTimeout