最近開發在解決Api接口超時問題時,發現我們的網關重試機制沒有生效,網關配置如下:
spring: cloud: loadbalancer: retry: enabled: true ribbon: ConnectTimeout: 1000 ReadTimeout: 1000 MaxAutoRetries: 0 MaxAutoRetriesNextServer: 1 OkToRetryOnAllOperations: false hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 4000 zuul: ignored-services: '*' semaphore: max-semaphores: 500 routes: blog_atang: path: /atang/** serviceId: blog-atang sensitiveHeaders: "*"
我聽到沒生效也比較詫異,因為參數都是正確的,至少實際使用過程中已經證明超時參數已經生效了,然而和開發再次一起測試,果然沒有觸發重試。又網上查了一些資料,總結網上的各種文檔一共有3個重試開關和一種重試策略。
第一個開關:ribbon.restclient.enabled=true ,這個不知道是不是SpringBoot版本的問題,我們加了以后也沒有觸發重試(我們的版本是SpringCloud Edgware.SR6,SpringBoot 1.5.22),但網上有篇文章使用的SpringCloud Greenwich.SR2,SpringBoot 2.1.3.RELEASE,開啟以后可以正常重試。
第二個開關:spring.cloud.loadbalancer.retry.enabled=true,有文章說這個參數可以開啟重試機制(默認值為false),但實際上我們默認就配置為true了,為了測試這個參數的效果,改成false以后,接口直接無法訪問了,此次問題主要是解決重試,所以就沒有去查看源碼深入研究此參數了。
第三個開關:zuul.retryable=true,這個開關需要引入spring-retry依賴才能使用:
<dependency> <groupId>org.springframework.retry</groupId> <artifactId>spring-retry</artifactId> </dependency>
但是很多文章雖然說了要引入此依賴,但是并沒有說配置zuul.retryable=true(默認為false),所以即使引入了依賴,超時路由也不會重試。
還支持只開啟指定路由重試,配置為:zuul.routes.<routename>.retryable=true。
還有一種重試方案就是采用ribbon的重試策略,配置為:ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RetryRule,實際測試并沒有觸發重試。關于Ribbon的負載均衡策略,可以參考如下介紹:
1、BestAvailabl
選擇一個最小的并發請求的 Server,逐個考察 Server,如果 Server 被標記為錯誤,則跳過,然后再選擇 ActiveRequestCount 中最小的 Server。
2、AvailabilityFilteringRule
過濾掉那些一直連接失敗的且被標記為 circuit tripped 的后端 Server,并過濾掉那些高并發的后端 Server 或者使用一個 AvailabilityPredicate 來包含過濾 Server 的邏輯。其實就是檢查 Status 里記錄的各個 Server 的運行狀態。
3、ZoneAvoidanceRule
使用 ZoneAvoidancePredicate 和 AvailabilityPredicate 來判斷是否選擇某個 Server,前一個判斷判定一個 Zone 的運行性能是否可用,剔除不可用的 Zone(的所有 Server),AvailabilityPredicate 用于過濾掉連接數過多的 Server。
4、RandomRule
隨機選擇一個 Server。
5、RoundRobinRule
輪詢選擇(默認策略),輪詢 index,選擇 index 對應位置的 Server。
6、RetryRule
對選定的負載均衡策略機上重試機制,也就是說當選定了某個策略進行請求負載時在一個配置時間段內若選擇 Server 不成功,則一直嘗試使用 subRule 的方式選擇一個可用的 Server。
7、ResponseTimeWeightedRule
作用同 WeightedResponseTimeRule,ResponseTime-Weighted Rule 后來改名為 WeightedResponseTimeRule。
8、WeightedResponseTimeRule
根據響應時間分配一個 Weight(權重),響應時間越長,Weight 越小,被選中的可能性越低。
總結,SpringCloud 版本為Edgware.x,SpringBoot 版本為1.5.x時,需要引入spring-retry,然后配置文件里面配置zuul.retryable=true,ribbon的重試參數才會生效。至于SpringBoot 2.x版本,按照網上有些文檔說明設置ribbon.restclient.enabled=true就會開啟重試,這個有待實測。經過此次問題,更加說明了不能太相信網上的文檔,而且搜索出來的文檔質量越來越差了,千篇一律;大多數情況只要有一篇原創發布,過幾天就會有很多相似的文檔就出來了,大部分是平臺采集,加上沒有實際測試的復制粘貼。所以阿湯博客運維文檔和其他技術文檔都是經過實際測試或者親身經歷的問題總結,如果有不全面的地方,可以留言討論。原創不易,復制請注明出處,謝謝。


