Hystrix

Hystrix

  • Hystrix 是用于處理延遲和容錯的開源庫;
  • Hystrix 主要用于避免級聯(lián)故障,提高系統(tǒng)彈性;
  • Hystrix 解決了由于扇出導(dǎo)致的“雪崩效應(yīng)”;
  • Hystrix 的核心是“隔離術(shù)”和“熔斷機制”;
關(guān)鍵詞
  • 扇出:服務(wù)的調(diào)用關(guān)系像一個思維導(dǎo)圖;
  • 雪崩:下游的服務(wù)掛了,上游的所有服務(wù)都超時;某個節(jié)點掛了,所有的流量都會打在另一個節(jié)點上,導(dǎo)致另一個節(jié)點也掛了,進而導(dǎo)致更多的節(jié)點掛了;

Hystrix | 主要作用

  • 服務(wù)隔離和服務(wù)熔斷;
  • 服務(wù)降級、快速失敗和限流;
  • 請求合并和請求緩存;
  • 自帶單體和集群監(jiān)控;

Hystrix | 主要步驟

Hystrix 架構(gòu)圖.png
  1. 調(diào)用 Main 方法
    1.1 Command
    1.2 ObservableCommand
  2. .execute() / .queue() / .observe() / .toObservable()
  3. 判斷有沒有請求緩存和請求合并,一定要開啟 HystrixRequestContext
  4. 熔斷有沒有開啟
  5. 限流有沒有觸發(fā)(線程池 / 信號量)
  6. 執(zhí)行業(yè)務(wù)方法
    6.1 業(yè)務(wù)執(zhí)行有沒有失敗
    6.2. 業(yè)務(wù)執(zhí)行有沒有超時
  7. 熔斷健康檢查
  8. 所有的失敗都會觸發(fā) fallback
  9. 業(yè)務(wù)直接返回

Hystrix | 兩種命令模式

兩種命令模式,可以分別執(zhí)行:.execute()、.queue()、.observe().toObservable()。

  • HystrixCommand
    • .execute()
    • .queue()
  • HystrixObservableCommand
    • .observe()
    • .toObservable()

.observe().toObservable() 的區(qū)別

  • .toObservable()new Subscriber<String>(){...} 中的 onNext() 可以集成正式的業(yè)務(wù)邏輯,在 run() 方法之外的業(yè)務(wù)邏輯;
  • .observe() 是 Hot 處理,在處理的過程中加載了一些東西,先執(zhí)行 Commandrun() 方法,再加載 / 注冊 Subscriber 對象;
  • .toObservable() 是 Cold 處理,在執(zhí)行之前就全部加載完,然后一次執(zhí)行完,先加載 / 注冊 Subscriber 對象,再執(zhí)行 Commandrun() 方法;
  • .toObservable() 每次訂閱都需要一個新的對象;

HystrixCommand 和 HystrixObservableCommand 的區(qū)別

  • HystrixCommand 以隔離的形式完成 run() 的調(diào)用,線程隔離;
  • HystrixObservableCommand 使用當前線程進行調(diào)用,信號量隔離,HystrixObservableCommand 一次可以執(zhí)行多個命令;

Hystrix | GroupKey

  • GroupKey 可以給 Hystrix 做分組和報警之用;
  • GroupKey 將作為線程池的默認名稱;

Hystrix | CommandKey

  • Hystrix 可以不填寫 CommandKey;
  • 默認 Hystrix 會通過反射類名命名 CommandKey;
  • 可以在 Setter 中加入 .andCommandKey() 來命名;

Hystrix | 請求緩存

  • Hystrix 支持將請求結(jié)果緩存在本地;
  • 通過實現(xiàn) getCacheKey 方法來判斷,是否取出緩存;
  • 請求緩存要求 Command 必須在同一個上下文中;
  • 通過 .withRequestCacheEnabled(true) 開啟請求緩存;

Hystrix | 請求合并

  • Hystrix 支持將多個請求合并成一次請求;
  • Hystrix 請求合并要求兩次請求必須足夠“近”,默認的閾值是 500ms;
  • 請求合并分為局部合并和全局合并;
  • Collapser 可以設(shè)置相關(guān)參數(shù);

Hystrix | 隔離術(shù)

ThreadPoolKey
  • 隔離一般都會用到線程池,線程池的話,一般都會起一個名字;
  • Hystrix 可以不填 ThreadPoolKey;
  • 默認 Hystrix 會用 GroupKey 命名線程池;
  • 在 Setter 中加入 andThreadPoolKey 進行命名;
隔離介紹
  • Hystrix 提供了信號量線程兩種隔離手段;
  • 線程隔離會在單獨的線程中執(zhí)行業(yè)務(wù)邏輯;
  • 信號量的話就是基于信號量模型做的隔離,信號量的隔離在調(diào)用線程(Main Thread)上執(zhí)行,但是調(diào)用的次數(shù)會做限制,超過這個次數(shù)的調(diào)用就不允許了;
隔離的好處
  • 比如一個請求進來了,請求了 3 個服務(wù),3 個服務(wù)在 3 個隔離的線程中執(zhí)行,2 個執(zhí)行成功了,1 個失敗了,失敗的服務(wù)并不會影響其他線程的執(zhí)行,可以快速失敗;

Hystrix | 降級處理

降級
  • 降級是一種無奈的選擇,就是俗稱的備胎;
  • 比如打發(fā)票打不出來了,降級成友好的提示;
  • 比如商品頁,推薦的商品顯示不出來了,將提前緩存的商品信息顯示在頁面上;
  • Command 在降級的時候,需要實現(xiàn) getFallback() 方法;
  • ObservableCommand 降級實現(xiàn) resumeWithFallback() 方法;
降級觸發(fā)原則
  • 除了 HystrixBadRequestException 之外的異常就會被降級;
  • 熔斷開啟的時候也會觸發(fā)降級;
  • 線程池或信號量滿的時候會被降級;
  • 業(yè)務(wù)異常會觸發(fā)降級;
  • 業(yè)務(wù)超時會觸發(fā)降級;
快速失敗
  • Hystrix 提供了快速失敗的機制,這個機制依賴的就是 getFallback(),當出現(xiàn)任何異常的時候,都會觸發(fā) getFallback(),getFallback() 就會把失敗的業(yè)務(wù)快速返回給前端;
  • 當不實現(xiàn) getFallback() 的時候,會將異常直接拋出,這也是一種快速失??;
快速失敗的好處
  • 在系統(tǒng)相互依賴調(diào)用的時候,快速失敗的存在,可以防止下游服務(wù)的不正常,卡住上游服務(wù),進一步導(dǎo)致級聯(lián)雪崩的情況;
  • 如果有快速失敗,下游不正常的服務(wù)快速失敗,上游服務(wù)就不會阻塞,業(yè)務(wù)還是可以正常辦理 ;

Hystrix | 熔斷機制

熔斷器介紹
  • 熔斷器是一種開關(guān),用來控制流量是否執(zhí)行業(yè)務(wù)邏輯;
  • 在熔斷器打開的時候,永遠執(zhí)行 getFallback(),永遠不執(zhí)行業(yè)務(wù)邏輯;
熔斷器核心指標

熔斷器的開關(guān),要么根據(jù) 3 個指標決定開關(guān),要么強制決定開關(guān)。邏輯是這樣的:在一個快照時間窗內(nèi),請求總數(shù)達到一定數(shù)后,看錯誤率,如果錯誤率超過閾值,打開熔斷開關(guān)。

  • 快照時間窗:就是一個時間段;
  • 請求總數(shù)閾值:在快照時間窗內(nèi)的請求總數(shù);
  • 錯誤百分比閾值:在快照時間窗內(nèi),錯誤的內(nèi)容達到一定比例,才觸發(fā)熔斷開關(guān);
熔斷器的核心
熔斷器核心.png
  • 每一個格代表一段時間,比如 1s;
  • 沒 10 個格會做一個匯總,就最后的白格;
  • 匯總的時候,如果發(fā)現(xiàn):請求的總數(shù)到閾值了,并且錯誤率到閾值了就打開熔斷器的開關(guān);
  • 這寫格是滾動的,新的一格接著隊尾,就把隊首的格丟掉;
  • 然后重新計算,如果不滿足打開熔斷器的條件,就將熔斷器關(guān)閉;
熔斷器的狀態(tài)
  • 開啟:所有請求對會進入 fallback 方法;
  • 半開啟:在熔斷器打開的狀態(tài)下,熔斷器會將請求每個幾秒放過去一個,看看服務(wù)恢復(fù)了沒有,如果恢復(fù)了,就關(guān)閉熔斷器,如此往復(fù)循環(huán);默認情況下,熔斷器開啟 5s 之后就會進入半開啟狀態(tài);
  • 關(guān)閉:正常處理業(yè)務(wù)請求;
Hystrix | 兩種應(yīng)用場景
  • 隱式創(chuàng)建 HystrixCommand:影廳服務(wù)調(diào)影片服務(wù)的邏輯,被封裝在 Command 的 run() 方法內(nèi),在 run() 方法內(nèi)發(fā)送了一次 HTTP 調(diào)用;當整合了 Feign 和 Zuul 的時候,HTTP 的調(diào)用就已經(jīng)整合進 HystrixCommand 中了;
  • 顯示創(chuàng)建 HystrixCommand:Controller 調(diào) Service 的邏輯被封裝在 Command 的 run() 方法內(nèi);
Hystrix Dashboard | 圖例
Hystrix Dashboard 圖例.png
Hystrix Dashboard | 缺陷
  • 只能監(jiān)控 2 分鐘內(nèi)的變化,不能監(jiān)控長時間的變化,并且不夠細致;
Hystrix | 設(shè)置線程池大小
  • Threadpool Size:比如系統(tǒng)的 QPS 是 3000,有 100 個節(jié)點,每個節(jié)點需要承載 30 的 QPS,請求的平均處理時間是 0.2s,那么需要的線程數(shù)就是 30 * 0.2 = 6 個線程,完了要加上 0.3~0.8 的冗余,比如線程切換之類的,差不多就是 10,Hystrix 默認的線程數(shù)量是 10,就可以承擔(dān) 30 的 QPS;
  • Threadpool Size:Threadpool Size 的 1.5~2 倍就可以;

Hystrix | 常見參數(shù)

請求上下文
配置 配置描述
requestCache.enabled 是否開啟請求緩存,默認為true
requestLog.enabled 是否開啟請求日志,默認為true
maxRequestsInBatch 設(shè)置批處理中允許的最大請求數(shù)
timerDelayInMilliseconds 設(shè)置批處理創(chuàng)建到執(zhí)行之間的毫秒數(shù)
線程池相關(guān)配置
配置 配置描述
coreSize 配置線程池大小,默認為10
keepAliveTimeMinutes 配置核心線程數(shù)空閑時keepAlived時長,默認1分鐘
maxQueueSize 配置線程池任務(wù)隊列大小,默認為-1
maximumSize 線程池中線程的最大數(shù)量,默認值是 10
queueSizeRejectionThreshold 任務(wù)隊列的請求上線,默認值是10
allowMaximumSizeToDivergeFromCoreSize 是否開啟最大線程數(shù)
execution.isolation.thread.timeoutInMilliseconds 設(shè)置超時時間
execution.isolation.thread.interruptOnTimeout 請求超時是否中斷任務(wù)
execution.isolation.thread.interruptOnCancel 請求取消是否終端任務(wù)
熔斷機制相關(guān)配置
配置 配置描述
circuitBreaker.enabled 是否開啟熔斷器
circuitBreaker.requestVolumeThreshold 啟用熔斷器功能窗口時間內(nèi)的最小請求數(shù)
circuitBreaker.sleepWindowInMilliseconds 半熔斷開啟時間
circuitBreaker.errorThresholdPercentage 開啟熔斷的失敗率閾值
最后編輯于
?著作權(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ù)。

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