Feign重試不生效問題的發現,主要還是因為上篇文章《SpringCloud Zuul(Ribbon)重試配置不生效解決辦法》里面介紹的原因。當我解決了Zuul重試不生效的問題,測試發現只有如下場景:zuul-->訪問A1、A2,A服務返回超時,也就是說Api接口的第一級跨度超過zuul配置ribbon.ReadTimeout的值才會觸發ribbon重試。場景一如下圖:

場景二如下圖,Api接口跨度多個服務的調用:

此時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重試參數性能實測對比》詳細介紹實際測試結果。


