SpringCloud openFeign遠端呼叫超時解決辦法
阿新 • • 發佈:2021-07-02
問題
在使用openFein進行遠端呼叫的時候,呼叫超時,報錯資訊如下:
com.netflix.hystrix.exception.HystrixRuntimeException: XXXService#login(RequestObject) timed-out and no fallback available.
原因
OpenFeign 內部集成了Hytrix
和 Ribbon
元件,當設定了
feign:
hystrix:
# 啟用fegin斷路器
enabled: true
,相當於啟用了斷路器,那麼呼叫的超時時間將會按照 Ribbon
和 Hytrix
的較小者去配置。
補充: 在引入了openFein
元件後,可以配置的內容如下所示:
1. hystrix可配置的部分: hystrix.command.default.execution.timeout.enable=true //為false則超時控制有ribbon控制,為true則hystrix超時和ribbon超時都是用,但是誰小誰生效,預設為true hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=3000//熔斷器的超時時長預設1秒,最常修改的引數 circuitBreaker.requestVolumeThreshold=20 //觸發熔斷的最小請求次數,預設為20 circuitBreaker.sleepWindowInMilliseconds=5000 //休眠時長,預設為5秒 circuitBreaker.errorThresholdPercentage=50 //觸發熔斷的失敗請求最小佔比,預設50% 2. ribbon可配置的部分: ribbon.ReadTimeout=1000 //處理請求的超時時間,預設為1秒 ribbon.ConnectTimeout=1000 //連線建立的超時時長,預設1秒 ribbon.MaxAutoRetries=1 //同一臺例項的最大重試次數,但是不包括首次呼叫,預設為1次 ribbon.MaxAutoRetriesNextServer=0 //重試負載均衡其他例項的最大重試次數,不包括首次呼叫,預設為0次 ribbon.OkToRetryOnAllOperations=false //是否對所有操作都重試,預設false 3. Feign可配置的部分: feign.hystrix.enable=false //feign是否啟用斷路器,預設為false
Ribbon的注意事項:
-
Ribbon的超時有2個:連線超時和處理超時,預設都是1秒。
-
Ribbon的預設重試也有2個:同一例項的重試次數和負載均衡的不同例項的重試次數,預設為1次和0次。
也就是說,如果只有一個例項,連線超時重試1次,處理超時也重試1次。即:實際Ribbon的超時時間是 1秒×2+1秒×2=4秒。
- Ribbon預設GET請求不論是連線失敗還是處理失敗都會重試,而對於非GET請求只對連線失敗進行重試。
結論:配置Hystrix的timeoutInMillisecond要大於Ribbon的 ( ConnectTimeout + ReadTimeout ) × 2。目的就是保證在熔斷之前完成遠端呼叫(包括Ribbon的重試時間)。
配置步驟配置步驟:
1. 開啟Feign的Hystrix開關
feign:
hystrix:
enabled: true
2. 設定Hystrix超時時長
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 15000
3. 配置ribbon的連線時長和服務響應時長
ribbon:
ConnectTimeout: 2000
ReadTimeout: 5000
解決
版本說明:SpringBoot:2.3.3.Release, OpenFeign: 2.2.7.Release
配置以下Feign
的配置:
feign:
hystrix:
# 啟用fegin斷路器
enabled: true
strategy:
custom: true # 自定義feign熔斷策略
httpclient:
enabled: true
okhttp:
enabled: false
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 15000
ribbon:
ConnectTimeout: 2000
ReadTimeout: 5000
問題解決,遠端呼叫微服務成功。