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

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

此時ReadTimeout有兩種情況:
1、Zuul網(wǎng)關的ribbon.ReadTimeout>服務端feign.client.config.default.readTimeout。
比如:Zuul網(wǎng)關的ribbon.ReadTimeout=3000,服務端配置的feign.client.config.default.readTimeout=1000,當請求從Zuul網(wǎng)關進來,負載均衡到任意的A服務節(jié)點,比如A1,此時A1通過feign調(diào)用B服務和C服務的任意節(jié)點,比如B2和C1。此時分兩種情況:
a.當A1并發(fā)請求B2和C1,此時如果有一個接口超時,或者兩個接口都超時,那么ReadTime都是1s左右,而并沒有達到ribbon.ReadTimeout=3000,所以不會觸發(fā)網(wǎng)關的ribbon重試,所以此時接口沒有返回正常的結果。
b.當A1順序請求B2和C1,此時如果有一個接口超時,那么ReadTime為1s左右,如果是兩個接口都超時,那么ReadTime都是2s左右,而并沒有達到ribbon.ReadTimeout=3000,所以不會觸發(fā)網(wǎng)關的ribbon重試,所以此時接口沒有返回正常的結果。
所以只要A服務處理請求的時間沒有超過在Zuul配置ribbon.ReadTimeout的值,那么都不會觸發(fā)ribbon的重試。
2、Zuul網(wǎng)關的ribbon.ReadTimeout=服務端feign.client.config.default.readTimeout。
比如:Zuul網(wǎng)關的ribbon.ReadTimeout=1000,服務端配置的feign.client.config.default.readTimeout=1000,當請求從Zuul網(wǎng)關進來,負載均衡到任意的A服務節(jié)點,比如A2,此時A2通過feign調(diào)用B服務和C服務的任意節(jié)點,比如B1和C2。此時不管是調(diào)用B1或者C2超時,或者都超時,那么都會觸發(fā)Zuul網(wǎng)關的ribbon重試,重試次數(shù)主要由ribbon.MaxAutoRetries和ribbon.MaxAutoRetriesNextServer配置的值決定。
比如ribbon.MaxAutoRetries=0,ribbon.MaxAutoRetriesNextServer=1那么,Zuul會根據(jù)配置,重新調(diào)用A1進行重試,而A1也是通過feign調(diào)隨機用B服務和C服務的任意節(jié)點。
總結以上兩種情況,A服務調(diào)用調(diào)用B服務或者C服務任意節(jié)點超時,A服務都不會對B服務和C服務的當前或者其他節(jié)點進行重試。
那么怎么樣,才能讓服務A調(diào)用服務B超時的時候,進行重試呢?網(wǎng)上找了些資料,總結如下:
1、Feign組件默認使用Ribbon的重試機制并增加了根據(jù)狀態(tài)碼判斷重試機制,默認情況下是不啟用的。
2、Feign使用的是Spring Retry組件,需要引入依賴才能啟用,也就是網(wǎng)關ribbon重試那個組件。
<dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency>
3、引入以后沒有正確配置ribbon,默認同一節(jié)點會重試5次,即使第一次訪問就觸發(fā)了Zuul網(wǎng)關已經(jīng)返回超時,并且瀏覽器已經(jīng)返回超時結果,F(xiàn)eign也會重試5次,如果剛好網(wǎng)關又觸發(fā)了重試,重試次數(shù)配置得也比較大的話,那么就會產(chǎn)生大量多余的請求,會對系統(tǒng)和服務性能造成一定的影響,哪怕沒有觸發(fā)網(wǎng)關的重試,出現(xiàn)一個節(jié)點某個服務故障的時候,也會產(chǎn)生多余的性能開銷。
4、根據(jù)網(wǎng)上找的資料服務端ribbon正確配置如下:
${spring.application.name}:
ribbon:
MaxAutoRetries: 1
MaxAutoRetriesNextServer: 1
OkToRetryOnAllOperations: false
NFLoadBalancerRuleClassName: AvailabilityFilteringRule
feign:
client:
config:
default:
connectTimeout: 1000
readTimeout: 1000
OkToRetryOnAllOperations建議不要設置為true,即使接口做了冪等,避免后續(xù)哪個接口忘記做冪等產(chǎn)生臟數(shù)據(jù)。
通過實際的測試,發(fā)現(xiàn)接入依賴以后,F(xiàn)eign的請求超時的確會觸發(fā)重試,但是實際上網(wǎng)關的ribbon.ReadTimeout、ribbon.MaxAutoRetries、ribbon.MaxAutoRetriesNextServer這些參數(shù)都會影響Feign的重試可能性和結果,下篇文章《SpringCloud Ribbon和Feign重試參數(shù)性能實測對比》詳細介紹實際測試結果。


