#參考官方配置 https://docs.spring.io/spring-cloud-openfeign/docs/2.2.5.RELEASE/reference/html/
feign:
client:
config:
default:
connectTimeout: 1000
readTimeout: 5000
hystrix:
enabled: true
#在feign和hystrix共存時,hystrix可以配置自身降級時間锻全,默認1s
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 10000 # 設(shè)置hystrix的超時時間為6000ms
circuitBreaker:
#在當10秒的時間內(nèi)狂塘,最近20次調(diào)用請求,請求錯誤率超過60%鳄厌,則觸發(fā)熔斷5秒荞胡,期間快速失敗,以下都是默認值
requestVolumeThreshold: 20
errorThresholdPercentage: 50
sleepWindowInMilliseconds: 5000
#設(shè)置統(tǒng)計的時間窗口值的毫秒值了嚎,circuit break 的打開會根據(jù)1個rolling window的統(tǒng)計來計算泪漂。
#若rolling window被設(shè)為10000毫秒廊营,則rolling window會被分成n個buckets,
#每個bucket包含success萝勤,failure露筒,timeout,rejection的次數(shù)的統(tǒng)計信息敌卓。默認10000慎式。
metrics:
rollingStats:
timeInMilliseconds: 10000
feign
-
ConnectTimeout
指的是建立連接所用的時間,適用于網(wǎng)絡(luò)狀況正常的情況下趟径,兩端連接所用的時間瘪吏。
在java中,網(wǎng)絡(luò)狀況正常的情況下蜗巧,例如使用HttpClient或者HttpURLConnetion連接時設(shè)置參數(shù)connectTimeout=5000即5秒肪虎,如果連接用時超過5秒就是拋出java.net.SocketException: connetct time out的異常 -
ReadTimeout
指的是建立連接后從服務(wù)器讀取到可用資源所用的時間。
在這里我們可以這樣理解ReadTimeout:正常情況下惧蛹,當我們發(fā)出請求時可以收到請求的結(jié)果扇救,也就是頁面上展示的內(nèi)容,但是當網(wǎng)絡(luò)狀況很差的時候香嗓,就會出現(xiàn)頁面上無法展示出內(nèi)容的情況迅腔。另外當我們使用爬蟲或者其他全自動的程序時,無法判斷當前的網(wǎng)絡(luò)狀況是否良好靠娱,此時就有了ReadTimeout的用武之地了沧烈,通過設(shè)置ReadTimeout參數(shù),例:ReadTimeout=5000像云,超過5秒沒有讀取到內(nèi)容時锌雀,就認為此次讀取不到內(nèi)容并拋出Java.net.SocketException: read time out的異常。
根據(jù)上面關(guān)于ConnectTimeout和ReadTimeout的描述迅诬,在我們使用需要設(shè)置這兩項參數(shù)的服務(wù)或程序時腋逆,應(yīng)該對兩項參數(shù)一起設(shè)置。
一般而言兩項參數(shù)的數(shù)值可以設(shè)置成一樣的侈贷,可以適當把ReadTimeout設(shè)置的長一點惩歉,ConnectTimeout可以相對比較短,這是源于我們的網(wǎng)絡(luò)狀況一般較為穩(wěn)定俏蛮,連接時很少出現(xiàn)問題撑蚌,但是讀取時因為數(shù)據(jù)下載時的網(wǎng)絡(luò)波動,出狀況的可能性更大一些搏屑。
測試争涌,
1. 雙邊連接良好
① 只設(shè)置hystrix(5s),feign的ReadTimeout辣恋、ConnectTimeout均不設(shè)置亮垫,服務(wù)方sleep1/2/3秒解幼,結(jié)果都如下:
調(diào)用方顯示了Read timed out,觸發(fā)了降級包警,并且有進行了重試撵摆,重試了1次,間隔1秒害晦。
############################# 第一次
1635755154447 --port : 7000 --- testHystrixSleep : 3
1635755155207 --port : 7000 --- testHystrixSleep : 3
############################# 第二次
1635755167963 --port : 7000 --- testHystrixSleep : 3
1635755168972 --port : 7000 --- testHystrixSleep : 3
由此可得 feign 的 readTimeout 默認是1s特铝。
② 設(shè)置hystrix(5s),feign的ReadTimeout為2s壹瘟,connectTimeout不設(shè)置:
服務(wù)方sleep 1s鲫剿,正常返回,
服務(wù)方sleep 2s稻轨,降級灵莲,沒有重試。
由此可得殴俱,在連接正常的情況下政冻,有設(shè)置readTimeout且少于請求時間,降級只取決于readTimeout的時間线欲。
③ 設(shè)置hystrix(5s)明场,feign的connectTimeout為1/2s,ReadTimeout不設(shè)置:
服務(wù)方sleep 2s李丰,無論connectTimeout是1s 還是 2s苦锨,均返回正常結(jié)果,沒有重試趴泌。
由此可得舟舒,在連接正常的情況下,readTimeout的默認時間(1s)是不起效的嗜憔,只取決于hystrix的時間秃励。
④ 設(shè)置hystrix(5s),feign的connectTimeout(1s)痹筛,ReadTimeout(2s)
服務(wù)方sleep 2s莺治,直接降級,沒有重試
⑤ 設(shè)置hystrix(3s)帚稠,feign的connectTimeout(1s),ReadTimeout(4s)
服務(wù)方sleep 3s床佳,直接降級滋早,沒有重試
服務(wù)方sleep 2s,正常返回
由此可得砌们,在連接正常的情況下杆麸,hystrix搁进、readTimeout的值取決于最小那個。
2. 停掉了服務(wù)方
①. 只設(shè)置hystrix(10s)昔头,feign的ReadTimeout饼问、ConnectTimeout均不設(shè)置,結(jié)果都如下
:
2021-11-01 18:12:57.906 DEBUG 20248 --- [trix-provider-1] c.orion.service.TestFeignHystrixService : [TestFeignHystrixService#providerHystrix] ---> GET http://provider/providerHystrix HTTP/1.1
2021-11-01 18:12:57.906 DEBUG 20248 --- [trix-provider-1] c.orion.service.TestFeignHystrixService : [TestFeignHystrixService#providerHystrix] ---> END HTTP (0-byte body)
由此可得一下就沒了。
②只設(shè)置hystrix(10s)揭斧,feign的ReadTimeout(4s)莱革、ConnectTimeout(2s)均設(shè)置,ConnectTimeout,結(jié)果都如下
2021-11-01 18:09:37.516 DEBUG 7852 --- [trix-provider-2] c.orion.service.TestFeignHystrixService : [TestFeignHystrixService#providerHystrix] ---> GET http://provider/providerHystrix HTTP/1.1
2021-11-01 18:09:37.517 DEBUG 7852 --- [trix-provider-2] c.orion.service.TestFeignHystrixService : [TestFeignHystrixService#providerHystrix] ---> END HTTP (0-byte body)
2021-11-01 18:09:39.537 DEBUG 7852 --- [trix-provider-2] c.orion.service.TestFeignHystrixService : [TestFeignHystrixService#providerHystrix] <--- ERROR SocketTimeoutException: connect timed out (2018ms)
由此可得還是取決 feign配置 的connectTimeout讹开。
總結(jié):
綜上可得盅视,其實在正常連接情況,都把connectTimeout配置比readTimeout小的旦万,hystrix默認是1秒闹击,而readTimeout也是1秒,但有時業(yè)務(wù)處理是不止1s的成艘,所以最好配置1s以上(不用默認值)赏半,在配置hystrix的同時,也要配置好connectTimeout和readTimeout淆两,而且上述測試可知除破,在readTimeout和hystrix同時在的情況下,誰小就誰決定降級時間琼腔,所以一般就把它們設(shè)置一樣就好了瑰枫。
----------------------------------- 分割線 -----------------------------------------
Hystrix的 局部降級 和 全局降級
首先看下,在上訴的例子里丹莲,得到的降級日志是怎么樣的光坝,我們能得到什么信息,為我們后續(xù)的局部甥材、全局的hystrix的配置提供有效信息盯另。
服務(wù)方會sleep 4s
,而調(diào)用方的配置如下:
feign:
hystrix:
enabled: true
okhttp:
enabled: true
client:
config:
default:
connectTimeout: 2000
readTimeout: 10000
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000 # 設(shè)置hystrix的超時時間,默認1s
2021-11-01 18:51:54.933 DEBUG 12268 --- [trix-provider-6] c.orion.service.TestFeignHystrixService : [TestFeignHystrixService#providerHystrix] ---> GET http://provider/providerHystrix HTTP/1.1
2021-11-01 18:51:54.933 DEBUG 12268 --- [trix-provider-6] c.orion.service.TestFeignHystrixService : [TestFeignHystrixService#providerHystrix] ---> END HTTP (0-byte body)
2021-11-01 18:51:57.942 DEBUG 12268 --- [trix-provider-6] c.orion.service.TestFeignHystrixService : [TestFeignHystrixService#providerHystrix] <--- ERROR SocketTimeoutException: Read timed out (3008ms)
2021-11-01 18:51:57.944 DEBUG 12268 --- [trix-provider-6] c.orion.service.TestFeignHystrixService : [TestFeignHystrixService#providerHystrix] java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
略...
2021-11-01 18:51:57.955 DEBUG 12268 --- [trix-provider-6] c.orion.service.TestFeignHystrixService : [TestFeignHystrixService#providerHystrix] <--- END ERROR
我們得到了 TestFeignHystrixService#providerHystrix
, 這是一個hystrixCommandKey洲赵,而hystrix配置的格式是這樣的:hystrix.command.<HystrixCommandKey>.execution.isolation.thread.timeoutInMilliseconds: 100 鸳惯,默認是default即全局,而如果我們需要自定義某個方法叠萍,即自定義hystrixCommonKey芝发,由日志得出,很顯然HystrixCommandKey就是@feignClient描述的接口類以及調(diào)用方法(帶參數(shù)類型)
組成的苛谷。
所以進行以下配置測試:(附帶上了circuitBreaker)
feign:
hystrix:
enabled: true
okhttp:
enabled: true
client:
config:
default:
connectTimeout: 2000
readTimeout: 10000
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 3000 # 設(shè)置hystrix的超時時間,默認1s
circuitBreaker:
#在當10秒的時間內(nèi)辅鲸,最近20次調(diào)用請求,請求錯誤率超過60%腹殿,則觸發(fā)熔斷5秒独悴,期間快速失敗例书,以下都是默認值
requestVolumeThreshold: 20
errorThresholdPercentage: 50
sleepWindowInMilliseconds: 5000
#設(shè)置統(tǒng)計的時間窗口值的毫秒值,circuit break 的打開會根據(jù)1個rolling window的統(tǒng)計來計算刻炒。
#若rolling window被設(shè)為10000毫秒决采,則rolling window會被分成n個buckets,
#每個bucket包含success坟奥,failure树瞭,timeout,rejection的次數(shù)的統(tǒng)計信息筏勒。默認10000移迫。
metrics:
rollingStats:
timeInMilliseconds: 10000
TestFeignHystrixService#providerPartHystrix(Integer):
execution:
isolation:
thread:
timeoutInMilliseconds: 5000 # 設(shè)置hystrix的超時時間,默認1s
circuitBreaker:
#在當10秒的時間內(nèi),最近20次調(diào)用請求管行,請求錯誤率超過60%厨埋,則觸發(fā)熔斷5秒,期間快速失敗捐顷,以下都是默認值
requestVolumeThreshold: 20
errorThresholdPercentage: 50
sleepWindowInMilliseconds: 5000
#設(shè)置統(tǒng)計的時間窗口值的毫秒值荡陷,circuit break 的打開會根據(jù)1個rolling window的統(tǒng)計來計算。
#若rolling window被設(shè)為10000毫秒迅涮,則rolling window會被分成n個buckets废赞,
#每個bucket包含success,failure叮姑,timeout唉地,rejection的次數(shù)的統(tǒng)計信息。默認10000传透。
metrics:
rollingStats:
timeInMilliseconds: 10000
提供了一個providerPartHystrix(Integer a) 方法:
@Service
@FeignClient(value = "provider", fallback = TestFeignHystrixServiceFallback.class)
public interface TestFeignHystrixService {
@GetMapping("/providerHystrix") //hystrix降級配置3秒 ,服務(wù)方sleep 4秒
Result providerHystrix();
@GetMapping("/providerPartHystrix") //hystrix降級配置5秒 ,服務(wù)方sleep 4秒
Result providerPartHystrix(@RequestParam("a") Integer a);
}
在進行請求后耘沼,http://127.0.0.1:8000/hystrix/providerPartHystrix,正常返回結(jié)果:
{"msg":"Success","code":1000,"data":"port : 7000 --- testPartHystrixSleep : 4 -- a : 1"}