springcloud之Feign超時問題的解決
問題背景
最近公司項目有個功能需進行三層Feign調用,且還要調外部接口,延遲挺大,造成Feign一直提示Read timed out executing POST。
feign.RetryableException: Read timed out executing POST http://****** at feign.FeignException.errorExecuting(FeignException.java:67) at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:104) at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:76) at feign.ReflectiveFeign$FeignInvocationHandler.invoke(ReflectiveFeign.java:103) at com.sun.proxy.$Proxy113.getBaseRow(Unknown Source) Caused by: java.net.SocketTimeoutException: Read timed out at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) at java.net.SocketInputStream.read(SocketInputStream.java:170) at java.net.SocketInputStream.read(SocketInputStream.java:141) at java.io.BufferedInputStream.fill(BufferedInputStream.java:246) at java.io.BufferedInputStream.read1(BufferedInputStream.java:286) at java.io.BufferedInputStream.read(BufferedInputStream.java:345) at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:704) at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:647) at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1569) at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1474) at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480) at feign.Client$Default.convertResponse(Client.java:152) at feign.Client$Default.execute(Client.java:74)
解決方案
首先,我們看下Feign的簡介
Feign 是一個聲明式的web服務客戶端,這便得編寫web服務客戶端更容易,使用Feign 創建一個接口並對它進行註解,它具有可插拔的註解支持包括Feign註解與JAX-RS註解,Feign還支持可插拔的編碼器與解碼器,Spring Cloud 增加瞭對 Spring MVC的註解,Spring Web 默認使用瞭HttpMessageConverters, Spring Cloud 集成 Ribbon 和 Eureka 提供的負載均衡的HTTP客戶端 Feign.
這麼說吧,Feign接口調用分兩層,Ribbon的調用和Hystrix調用,理論上設置Ribbon的時間即可,但是Ribbon的超時時間和Hystrix的超時時間需要結合起來,按照木桶原則最低的就是Feign的超時時間,建議最好配置超時時間一致。經過配置一下application設置後,完美解決瞭問題。因為第三方接口中需要3~20秒不等的時間,所以這個數值也是根據自己的業務系統情況設置的。
application.xml
#hystrix的超時時間 hystrix: command: default: execution: timeout: enabled: true isolation: thread: timeoutInMilliseconds: 30000 #ribbon的超時時間 ribbon: ReadTimeout: 30000 ConnectTimeout: 30000
springcloud之Feign 負載均衡請求超時時間
SpringCloud:Greenwich.SR4
SpringBoot:2.1.9.RELEASE
Feign調用服務的默認時長是1秒鐘,也就是如果超過1秒沒連接上或者超過1秒沒響應,那麼會相應的報錯。
但是在實際的業務中,我們的服務可能因為特別原因(網絡、處理壓力大等)導致相應速度超過1秒鐘,那麼就會報錯,下面我們就來處理如何手動配置Feigin的負載均衡超時等參數
全局配置
SpringCloud負載均衡底層用的就是Ribbon
#--------------Feign負載均衡配置 配置全局超時時間 ribbon: ConnectTimeout: 5000 #請求連接的超時時間,默認時間為1秒 ReadTimeout: 5000 #請求處理的超時時間
5秒沒有響應成功就報如下錯誤(真實情況下,會比5s多一些,因為發送請求也需要時間的,模擬超時可以在請求處理的方法上用Thread.sleep()設置休眠時間超過5s)
局部配置(就是指定提供者)
#--------------Feign負載均衡配置 局部配置超時時間等 feign-product-provider: #指定配置的服務名稱 ribbon: OkToRetryOnAllOperations: true # 對所有請求都進行重試 MaxAutoRetries: 2 # 對當前實例的重試次數 MaxAutoRetriesNextServer: 0 # 切換實例的重試次數(集群狀態下,其它對其它實例服務重試的次數) ConnectTimeout: 3000 # 請求連接的超時時間 ReadTimeout: 3000 # 請求處理的超時時間
上述提到的服務名稱如下配置
spring: application: name: feign-product-provider # 隨意設置
執行的代碼
輸出結果
不是一共重試兩次嗎?這裡邊就涉及到瞭一個公式
共重試次數 = (MaxAutoRetries+MaxAutoRetriesNextServer+(MaxAutoRetries * MaxAutoRetiresNextServer)
= 2 + 0 + (2 * 0)
= 2
在加上我們手動請求一次那就是:2 + 1=3次
公式很重要!
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- Feign Client 超時時間配置不生效的解決
- 基於springboot服務間Feign調用超時的解決方案
- 基於FeignClient調用超時的處理方案
- 如何解決springcloud feign 首次調用100%失敗的問題
- SpringBoot 關於Feign的超時時間配置操作