SpringCloud Feign重試不生效問題排查

2020年9月28日16:22:07 發(fā)表評論 6,484 ℃

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

SpringCloud Feign重試不生效問題排查

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

SpringCloud Feign重試不生效問題排查

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

【騰訊云】云服務器、云數(shù)據(jù)庫、COS、CDN、短信等云產(chǎn)品特惠熱賣中

發(fā)表評論

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