FeignClient spi 調用 短路異常 & 線程池配置
默認配置見:
HystrixThreadPoolProperties
線程池對象:com.netflix.hystrix.HystrixThreadPool
1. 問題
最近項目中使用FeignClient 調用公共消息服務的spi時候,突然出現了一下錯誤:
MessageSpi.sendMessage could not be queued for execution and fallback disabled.
然后很快出現了短路錯誤:
MessageSpi.sendMessage short-circuited and fallback disabled.
2. 依賴接口性能解決
反饋給接口提供方后,他們說是調用方配置的線程池滿了,而為什么滿,他們懷疑是自己的接口性能慢導致。所以他們去優化接口的性能即可。我們無需關注線程池滿的原因。
不過問題很快又找到我了。
接下來的另一個項目是一個類似請求轉發&返回值封裝的中間層服務,主要請求都是通過SPI的方式調用其他服務。結果在壓測時一下子就報錯誤了,和上面提到的錯誤是一樣的。
這個時候,如果還是找接口性能就不那么靠譜了。因為即使接口性能在100ms的情況下,支持100qps的並發還是很easy。
3. 原因
后面通過本地斷點,發現FeignClient使用的線程池是com.netflix.hystrix.HystrixThreadPool,然后內部使用的還是ThreadPoolExecutor,他默認的線程池數量是10(可以從HystrixThreadPoolProperties 這里看到),隊列-1,表示同步隊列。
而組件里配置的默認線程池大小是30,隊列的大小也是30.
假設接口性能在 50ms,那么這個配置,最大的qps 應該是 30 * (1000/50),也就是 600qps。
表面上看這個配置是夠用的,但是依賴接口的性能,因為如果是100ms ,那么就瞬間降到300qps。
而按照默認的配置,這個值是200qps,要求低一點就是100qps。
而且可能由於瞬時的流量,導致響應慢后隊列就很可能慢,然后導致了以上的錯誤。
4. 根據你的業務場景來配置
2中的問題不一樣,他是一個流量轉發的任務,在本地耗時的時間短,基本都是spi耗時,所以它的線程池的配置應該是和該服務容器線程差不多才行。
所以我們線程池的配置如下:
hystrix:
threadpool:
default:
coreSize: 200 #並發執行的最大線程數,默認10
maxinumPoolSize: 300 # 最大線程數
maxQueueSize: 100 #BlockingQueue的最大隊列數,默認值-1
queueSizeRejectionThreshold: 80 #即使maxQueueSize沒有達到,達到queueSizeRejectionThreshold該值后,請求也會被拒絕,默認值5
另外,default是 默認的配置,從com.netflix.hystrix.HystrixThreadPool.Factory#threadPools這里我們可以看到,線程池的配置還可以按照不同的FeignClient
配置不同的線程池,依據你自己的場景去配置就好
hystrix:
threadpool:
message-server: # 對應 message-sever 對應的 FeignClient SPI
coreSize: 200
maxinumPoolSize: 300 # 最大線程數
maxQueueSize: 100 #BlockingQueue的最大隊列數,默認值-1
queueSizeRejectionThreshold: 80
