開(kāi)篇
?對(duì)Hystrix耳聞已久甸私,最近剛好想在項(xiàng)目中使用這個(gè)神器就順帶研究了一把帆赢,很多細(xì)節(jié)來(lái)不及深入研究只能把宏觀上的各個(gè)概念講解一下颈抚,這個(gè)介紹的素材大都來(lái)自github上的Hystrix官網(wǎng)蝌借。
?所謂一圖勝千言衙传,但凡能夠用圖片來(lái)表示而且能夠表示清楚的嘱支,就不多用文字描述了蚓胸,看圖肯定比看文字要讓人來(lái)的更爽一些。當(dāng)然我還是非常建議去github上的Hystrix官方wiki去看原汁原味的文檔除师,在參考文獻(xiàn)部分已經(jīng)給出了鏈接沛膳。
?最后提一點(diǎn),就是在Hystrix的實(shí)現(xiàn)當(dāng)中大量使用了RxJava的開(kāi)源包的技術(shù)馍盟,這個(gè)技術(shù)之前沒(méi)怎么研究過(guò)于置,所以后面的很多源碼的分析更多側(cè)重過(guò)程分析而不會(huì)深入細(xì)節(jié),有興趣的可以自己深入研究下贞岭,我就準(zhǔn)備哪天得空好好去研究一下八毯,畢竟RxJava這個(gè)東西號(hào)稱是一個(gè)通過(guò)使用可觀察序列來(lái)編寫(xiě)異步和基于事件的程序的庫(kù)。
Hystrix的設(shè)計(jì)理念
- Give protection from and control over latency and failure from dependencies accessed (typically over the network) via third-party client libraries.
給依賴于第三方庫(kù)的應(yīng)用程序提供給保護(hù) - Stop cascading failures in a complex distributed system.
在復(fù)雜的分布式系統(tǒng)當(dāng)中避免級(jí)聯(lián)失敗 - Fail fast and rapidly recover.
快速失敗并且快速恢復(fù) - Fallback and gracefully degrade when possible.
在可能的情況下提供回退和優(yōu)雅降級(jí)的能力 - Enable near real-time monitoring, alerting, and operational control.
通過(guò)近乎實(shí)時(shí)的指標(biāo)瞄桨,監(jiān)控和警報(bào)來(lái)優(yōu)化發(fā)現(xiàn)故障的時(shí)間话速。
Hystrix提供的能力
?hystrix的出現(xiàn)即為解決雪崩效應(yīng),它通過(guò)四個(gè)方面的機(jī)制來(lái)解決這個(gè)問(wèn)題
- 隔離(線程池隔離和信號(hào)量隔離):限制調(diào)用分布式服務(wù)的資源使用芯侥,某一個(gè)調(diào)用的服務(wù)出現(xiàn)問(wèn)題不會(huì)影響其他服務(wù)調(diào)用泊交。
- 優(yōu)雅的降級(jí)機(jī)制:超時(shí)降級(jí)、資源不足時(shí)(線程或信號(hào)量)降級(jí)柱查,降級(jí)后可以配合降級(jí)接口返回托底數(shù)據(jù)廓俭。
- 熔斷:當(dāng)失敗率達(dá)到閥值自動(dòng)觸發(fā)降級(jí)(如因網(wǎng)絡(luò)故障/超時(shí)造成的失敗率高),熔斷器觸發(fā)的快速失敗會(huì)進(jìn)行快速恢復(fù)唉工。
- 緩存:提供了請(qǐng)求緩存研乒、請(qǐng)求合并實(shí)現(xiàn)。
- 支持實(shí)時(shí)監(jiān)控淋硝、報(bào)警雹熬、控制
Hystrix-隔離
?Hystrix的隔離主要是為每個(gè)依賴組件提供一個(gè)隔離的線程環(huán)境,提供兩種模式的隔離:
- 線程池隔離模式:使用一個(gè)線程池來(lái)存儲(chǔ)當(dāng)前的請(qǐng)求谣膳,線程池對(duì)請(qǐng)求作處理竿报,設(shè)置任務(wù)返回處理超時(shí)時(shí)間,堆積的請(qǐng)求堆積入線程池隊(duì)列继谚。這種方式需要為每個(gè)依賴的服務(wù)申請(qǐng)線程池烈菌,有一定的資源消耗,好處是可以應(yīng)對(duì)突發(fā)流量(流量洪峰來(lái)臨時(shí),處理不完可將數(shù)據(jù)存儲(chǔ)到線程池隊(duì)里慢慢處理)
- 信號(hào)量隔離模式:使用一個(gè)原子計(jì)數(shù)器(或信號(hào)量)來(lái)記錄當(dāng)前有多少個(gè)線程在運(yùn)行僧界,請(qǐng)求來(lái)先判斷計(jì)數(shù)器的數(shù)值侨嘀,若超過(guò)設(shè)置的最大線程個(gè)數(shù)則丟棄改類型的新請(qǐng)求,若不超過(guò)則執(zhí)行計(jì)數(shù)操作請(qǐng)求來(lái)計(jì)數(shù)器+1捂襟,請(qǐng)求返回計(jì)數(shù)器-1咬腕。這種方式是嚴(yán)格的控制線程且立即返回模式,無(wú)法應(yīng)對(duì)突發(fā)流量(流量洪峰來(lái)臨時(shí)葬荷,處理的線程超過(guò)數(shù)量涨共,其他的請(qǐng)求會(huì)直接返回,不繼續(xù)去請(qǐng)求依賴的服務(wù))
線程池隔離 | 信號(hào)量隔離 | |
---|---|---|
線程 | 與調(diào)用線程不相同線程 | 與調(diào)用線程相同 |
開(kāi)銷 | 排隊(duì)宠漩、調(diào)度举反、上下文開(kāi)銷等 | 無(wú)線程切換,開(kāi)銷低 |
異步 | 支持 | 不支持 |
并發(fā)支持 | 支持(最大線程池大邪怯酢) | 支持(最大信號(hào)量上限) |
Hystrix-熔斷器
?Hystrix的熔斷器其實(shí)可以理解為就是一個(gè)統(tǒng)計(jì)中心火鼻,統(tǒng)計(jì)一定時(shí)間窗口內(nèi)訪問(wèn)次數(shù),成功次數(shù)雕崩,失敗次數(shù)等數(shù)值判定是否發(fā)生熔斷魁索。發(fā)生電路熔斷的過(guò)程如下:
- 假設(shè)電路上的音量達(dá)到一定閾值(HystrixCommandProperties.circuitBreakerRequestVolumeThreshold)
- 并假設(shè)錯(cuò)誤百分比超過(guò)閾值錯(cuò)誤百分比(HystrixCommandProperties.circuitBreakerErrorThresholdPercentage)
- 然后斷路器從CLOSED轉(zhuǎn)換到OPEN。
- 它是開(kāi)放的盼铁,它使所有針對(duì)該斷路器的請(qǐng)求短路粗蔚。
- 經(jīng)過(guò)一段時(shí)間(HystrixCommandProperties.circuitBreakerSleepWindowInMilliseconds),下一個(gè)單個(gè)請(qǐng)求是通過(guò)(這是HALF-OPEN狀態(tài))饶火。 如果請(qǐng)求失敗鹏控,斷路器將在睡眠窗口持續(xù)時(shí)間內(nèi)返回到OPEN狀態(tài)。 如果請(qǐng)求成功肤寝,斷路器將轉(zhuǎn)換到CLOSED当辐,邏輯1.重新接管。
Hystrix工作流程
- 構(gòu)建一個(gè)HystrixCommand或者HystrixObservableCommand 對(duì)象鲤看。
- 執(zhí)行Command
- 響應(yīng)是否有緩存缘揪?如果為該命令啟用請(qǐng)求緩存,并且如果緩存中對(duì)該請(qǐng)求的響應(yīng)可用刨摩,則此緩存響應(yīng)將立即以“可觀察”的形式返回寺晌。
- 熔斷器是否打開(kāi)世吨?如果電路打開(kāi)(或“跳閘”)澡刹,則Hystrix將不會(huì)執(zhí)行該命令,但會(huì)將流程路由到(8)獲取回退耘婚。如果電路關(guān)閉罢浇,則流程進(jìn)行到(5)以檢查是否有可用于運(yùn)行命令的容量。
- 線程池/隊(duì)列/信號(hào)量是否已經(jīng)滿負(fù)載?如果與命令相關(guān)聯(lián)的線程池和隊(duì)列(或信號(hào)量嚷闭,如果不在線程中運(yùn)行)已滿攒岛,則Hystrix將不會(huì)執(zhí)行該命令,但將立即將流程路由到(8)獲取回退胞锰。
- 執(zhí)行真正的命令部分灾锯,HystrixObservableCommand.construct() 或者 HystrixCommand.run(),在這里Hystrix通過(guò)您為此目的編寫(xiě)的方法調(diào)用對(duì)依賴關(guān)系的請(qǐng)求嗅榕。如果run或construct方法超出了命令的超時(shí)值顺饮,則該線程將拋出一個(gè)TimeoutException, 在這種情況下,Hystrix將響應(yīng)通過(guò)8進(jìn)行路由凌那。獲取Fallback兼雄,如果該方法不取消/中斷,它會(huì)丟棄最終返回值run()或construct()方法帽蝶。
- 計(jì)算Circuit 的健康赦肋,Hystrix向斷路器報(bào)告成功,失敗励稳,拒絕和超時(shí)佃乘,該斷路器維護(hù)了一系列的計(jì)算統(tǒng)計(jì)數(shù)據(jù)組。它使用這些統(tǒng)計(jì)信息來(lái)確定電路何時(shí)“跳閘”麦锯,此時(shí)短路任何后續(xù)請(qǐng)求直到恢復(fù)時(shí)間過(guò)去恕稠,在首次檢查某些健康檢查之后,它再次關(guān)閉電路扶欣。
- 獲取Fallback鹅巍,當(dāng)命令執(zhí)行失敗時(shí),Hystrix試圖恢復(fù)到你的回退:當(dāng)construct或run拋出異常時(shí)[6]料祠,當(dāng)命令由于電路斷開(kāi)而短路時(shí)[4]骆捧,當(dāng)命令的線程池和隊(duì)列或信號(hào)量處于容量[5],或者當(dāng)命令超過(guò)其超時(shí)長(zhǎng)度時(shí)[6]髓绽。
- 返回成功的響應(yīng)敛苇,如果 Hystrix command成功,如果Hystrix命令成功,它將以O(shè)bservable的形式返回對(duì)呼叫者的響應(yīng)或響應(yīng)邓夕。