在生活中,如果電路的負(fù)載過(guò)高,保險(xiǎn)箱會(huì)自動(dòng)跳閘,以保護(hù)家里的各種電器,這就是熔斷器的一個(gè)活生生例子。在Hystrix中也存在這樣一個(gè)熔斷器,當(dāng)所依賴的服務(wù)不穩(wěn)定時(shí),能夠自動(dòng)熔斷,并提供有損服務(wù),保護(hù)服務(wù)的穩(wěn)定性。在運(yùn)行過(guò)程中,Hystrix會(huì)根據(jù)接口的執(zhí)行狀態(tài)(成功、失敗、超時(shí)和拒絕),收集并統(tǒng)計(jì)這些數(shù)據(jù),根據(jù)這些信息來(lái)實(shí)時(shí)決策是否進(jìn)行熔斷。
相關(guān)參數(shù)
Hystrix的熔斷器實(shí)現(xiàn)在HystrixCircuitBreaker類(lèi)中,比較重要的幾個(gè)參數(shù)如下:
1、circuitBreaker.enabled
熔斷器是否啟用,默認(rèn)是true
2、circuitBreaker.forceOpen
熔斷器強(qiáng)制打開(kāi),始終保持打開(kāi)狀態(tài),默認(rèn)是false
3、circuitBreaker.forceClosed
熔斷器強(qiáng)制關(guān)閉,始終保持關(guān)閉狀態(tài),默認(rèn)是false
4、circuitBreaker.requestVolumeThreshold
滑動(dòng)窗口內(nèi)(10s)的請(qǐng)求數(shù)閾值,只有達(dá)到了這個(gè)閾值,才有可能熔斷。默認(rèn)是20,如果這個(gè)時(shí)間段只有19個(gè)請(qǐng)求,就算全部失敗了,也不會(huì)自動(dòng)熔斷。
5、circuitBreaker.errorThresholdPercentage
錯(cuò)誤率閾值,默認(rèn)50%,比如(10s)內(nèi)有100個(gè)請(qǐng)求,其中有60個(gè)發(fā)生異常,那么這段時(shí)間的錯(cuò)誤率是60,已經(jīng)超過(guò)了錯(cuò)誤率閾值,熔斷器會(huì)自動(dòng)打開(kāi)。
6、circuitBreaker.sleepWindowInMilliseconds
熔斷器打開(kāi)之后,為了能夠自動(dòng)恢復(fù),每隔默認(rèn)5000ms放一個(gè)請(qǐng)求過(guò)去,試探所依賴的服務(wù)是否恢復(fù)。
工作原理
詳細(xì)過(guò)程如下:

在最新代碼中,因?yàn)橐恍゜ug,已經(jīng)棄用了allowRequest(),取而代之的是attemptExecution()方法。

和allowRequest() 方法相比,唯一改進(jìn)的地方是通過(guò)compareAndSet修改狀態(tài)值。通過(guò)attemptExecution()方法的返回值決定執(zhí)行正常邏輯,還是降級(jí)邏輯。
1、如果circuitBreaker.forceOpen=true,說(shuō)明熔斷器已經(jīng)強(qiáng)制開(kāi)啟,所有請(qǐng)求都會(huì)被熔斷。
2、如果circuitBreaker.forceClosed =true,說(shuō)明熔斷器已經(jīng)強(qiáng)制關(guān)閉,所有請(qǐng)求都會(huì)被放行。
3、circuitOpened默認(rèn)-1,用以保存最近一次發(fā)生熔斷的時(shí)間戳。
4、如果circuitOpened不等于 -1,說(shuō)明已經(jīng)發(fā)生熔斷,通過(guò)isAfterSleepWindow()判斷當(dāng)前是否需要進(jìn)行試探。

這里就是熔斷器自動(dòng)恢復(fù)的邏輯,如果當(dāng)前時(shí)間已經(jīng)超過(guò)上次熔斷的時(shí)間戳 + 試探窗口5000ms,則進(jìn)入if分支,通過(guò)compareAndSet修改變量status,競(jìng)爭(zhēng)試探的能力。其中status代表當(dāng)前熔斷器的狀態(tài),包含CLOSED, OPEN, HALF_OPEN,只有試探窗口之后的第一個(gè)請(qǐng)求可以執(zhí)行正常邏輯,且修改當(dāng)前狀態(tài)為HALF_OPEN,進(jìn)入半熔斷狀態(tài),其它請(qǐng)求執(zhí)行compareAndSet(Status.OPEN, Status.HALF_OPEN)時(shí)都返回false,執(zhí)行降級(jí)邏輯。
5、如果試探請(qǐng)求發(fā)生異常,則執(zhí)行markNonSuccess()

通過(guò)compareAndSet修改status為熔斷開(kāi)啟狀態(tài),并更新當(dāng)前熔斷開(kāi)啟的時(shí)間戳。
6、如果試探請(qǐng)求返回成功,則執(zhí)行markSuccess()

通過(guò)compareAndSet修改status為熔斷關(guān)閉狀態(tài),并重置接口統(tǒng)計(jì)數(shù)據(jù)和circuitOpened標(biāo)識(shí)為-1,后續(xù)請(qǐng)求開(kāi)始執(zhí)行正常邏輯。
說(shuō)了這么多,如何實(shí)現(xiàn)自動(dòng)熔斷還沒(méi)提到,在Hystrix內(nèi)部有一個(gè)Metric模塊,專(zhuān)門(mén)統(tǒng)計(jì)每個(gè)Command的執(zhí)行狀態(tài),包括成功、失敗、超時(shí)、線程池拒絕等,在熔斷器的中subscribeToStream()方法中,通過(guò)訂閱數(shù)據(jù)流變化,實(shí)現(xiàn)函數(shù)回調(diào),當(dāng)有新的請(qǐng)求時(shí),數(shù)據(jù)流發(fā)生變化,觸發(fā)回調(diào)函數(shù)onNext

在onNext方法中,參數(shù)hc保存了當(dāng)前接口在前10s之內(nèi)的請(qǐng)求狀態(tài)(請(qǐng)求總數(shù)、失敗數(shù)和失敗率),其主要邏輯是判斷請(qǐng)求總數(shù)是否達(dá)到閾值requestVolumeThreshold,失敗率是否達(dá)到閾值errorThresholdPercentage,如果都滿足,說(shuō)明接口的已經(jīng)足夠的不穩(wěn)定,需要進(jìn)行熔斷,則設(shè)置status為熔斷開(kāi)啟狀態(tài),并更新circuitOpened為當(dāng)前時(shí)間戳,記錄上次熔斷開(kāi)啟的時(shí)間。