Hystrix兩種隔離模式分析

個人專題目錄


1.hystrix 隔離模式目前有兩種方式:信號量模式和線程池模式。

但信號量并不支持超時,當被調(diào)服務(wù)發(fā)生問題時,有少部分用戶會長時間無法得到響應(yīng)。

另外,使用線程池模式無法傳遞 Header,我估計是由于線程切換,參數(shù)傳遞過程中被去掉了。

587aed6cdd284d3995246e5eaf890c35-image.png

目前 hystrix 熔斷器支持的隔離策略主要是信號量和線程池兩種方式

信號量的使用示意圖如下圖所示,當 n 個并發(fā)請求去調(diào)用一個目標服務(wù)接口時,都要獲取一個信號量才能真正去調(diào)用目標服務(wù)接口,但信號量有限,默認是 10 個,可以使用 maxConcurrentRequests 參數(shù)配置,如果并發(fā)請求數(shù)多于信號量個數(shù),就有線程需要進入隊列排隊,但排隊隊列也有上限,默認是 5,如果排隊隊列也滿,則必定有請求線程會走 fallback 流程,從而達到限流和防止雪崩的目的。

07122136uv5i.png

信號量模式從始至終都只有請求線程自身,是同步調(diào)用模式,不支持超時調(diào)用,不支持直接熔斷,由于沒有線程的切換,開銷非常小。

  • 信號隔離也可以用于限制并發(fā)訪問,防止阻塞擴散, 與線程隔離最大不同在于執(zhí)行依賴代碼的線程依然是請求線程(該線程需要通過信號申請),
  • 如果客戶端是可信的且可以快速返回,可以使用信號隔離替換線程隔離,降低開銷.
  • 信號量的大小可以動態(tài)調(diào)整, 線程池大小不可以.

線程池的使用示意圖如下圖所示,當 n 個請求線程并發(fā)對某個接口請求調(diào)用時,會先從 hystrix 管理的線程池里面獲得一個線程,然后將參數(shù)傳遞給這個線程去執(zhí)行真正調(diào)用。線程池的大小有限,默認是 10 個線程,可以使用 maxConcurrentRequests 參數(shù)配置,如果并發(fā)請求數(shù)多于線程池線程個數(shù),就有線程需要進入隊列排隊,但排隊隊列也有上限,默認是 5,如果排隊隊列也滿,則必定有請求線程會走 fallback 流程。

線程池模式可以支持異步調(diào)用,支持超時調(diào)用,支持直接熔斷,存在線程切換,開銷大。

把執(zhí)行依賴代碼的線程與請求線程(如:jetty線程)分離,請求線程可以自由控制離開的時間(異步過程)。

通過線程池大小可以控制并發(fā)量,當線程池飽和時可以提前拒絕服務(wù),防止依賴問題擴散。

線上建議線程池不要設(shè)置過大,否則大量堵塞線程有可能會拖慢服務(wù)器。

  • (2)線程隔離的優(yōu)缺點

    • 線程隔離的優(yōu)點:
    • 使用線程可以完全隔離第三方代碼,請求線程可以快速放回
    • 當一個失敗的依賴再次變成可用時,線程池將清理,并立即恢復可用,而不是一個長時間的恢復
    • 可以完全模擬異步調(diào)用,方便異步編程
    • 線程隔離的缺點:
    • 線程池的主要缺點是它增加了cpu,因為每個命令的執(zhí)行涉及到排隊(默認使用SynchronousQueue避免排隊),調(diào)度和上下文切換
    • 對使用ThreadLocal等依賴線程狀態(tài)的代碼增加復雜性,需要手動傳遞和清理線程狀態(tài)。
    • NOTE: Netflix公司內(nèi)部認為線程隔離開銷足夠小,不會造成重大的成本或性能的影響。

      • Netflix 內(nèi)部API 每天100億的HystrixCommand依賴請求使用線程隔,每個應(yīng)用大約40多個線程池,每個線程池大約5-20個線程。
07122201jfas.png

2.Hystrix如何解決依賴隔離

  • 1:Hystrix使用命令模式HystrixCommand(Command)包裝依賴調(diào)用邏輯,每個命令在單獨線程中/信號授權(quán)下執(zhí)行。
  • 2:可配置依賴調(diào)用超時時間,超時時間一般設(shè)為比99.5%平均時間略高即可.當調(diào)用超時時,直接返回或執(zhí)行fallback邏輯。
  • 3:為每個依賴提供一個小的線程池(或信號),如果線程池已滿調(diào)用將被立即拒絕,默認不采用排隊.加速失敗判定時間。
  • 4:依賴調(diào)用結(jié)果分:成功,失敗(拋出異常),超時,線程拒絕,短路。 請求失敗(異常,拒絕,超時,短路)時執(zhí)行fallback(降級)邏輯。
  • 5:提供熔斷器組件,可以自動運行或手動調(diào)用,停止當前依賴一段時間(10秒),熔斷器默認錯誤率閾值為50%,超過將自動運行。
  • 6:提供近實時依賴的統(tǒng)計和監(jiān)控

3.Hystrix流程結(jié)構(gòu)解析

img
流程說明:
1:每次調(diào)用創(chuàng)建一個新的HystrixCommand,把依賴調(diào)用封裝在run()方法中.
2:執(zhí)行execute()/queue做同步或異步調(diào)用.
3:判斷熔斷器(circuit-breaker)是否打開,如果打開跳到步驟8,進行降級策略,如果關(guān)閉進入步驟.
4:判斷線程池/隊列/信號量是否跑滿,如果跑滿進入降級步驟8,否則繼續(xù)后續(xù)步驟.
5:調(diào)用HystrixCommand的run方法.運行依賴邏輯
5a:依賴邏輯調(diào)用超時,進入步驟8.
6:判斷邏輯是否調(diào)用成功
6a:返回成功調(diào)用結(jié)果
6b:調(diào)用出錯,進入步驟8.
7:計算熔斷器狀態(tài),所有的運行狀態(tài)(成功, 失敗, 拒絕,超時)上報給熔斷器,用于統(tǒng)計從而判斷熔斷器狀態(tài).
8:getFallback()降級邏輯.
  以下四種情況將觸發(fā)getFallback調(diào)用:
 (1):run()方法拋出非HystrixBadRequestException異常。
 (2):run()方法調(diào)用超時
 (3):熔斷器開啟攔截調(diào)用
 (4):線程池/隊列/信號量是否跑滿
8a:沒有實現(xiàn)getFallback的Command將直接拋出異常
8b:fallback降級邏輯調(diào)用成功直接返回
8c:降級邏輯調(diào)用失敗拋出異常
9:返回執(zhí)行成功結(jié)果

4.熔斷器:Circuit Breaker

每個熔斷器默認維護10個bucket,每秒一個bucket,每個bucket記錄成功,失敗,超時,拒絕的狀態(tài),

默認錯誤超過50%且10秒內(nèi)超過20個請求進行中斷攔截.

img
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容