防雪崩利器:熔斷器 Hystrix 的原理與使用

也可參考 https://segmentfault.com/a/1190000005988895

我們知道大量請求會阻塞在Tomcat服務器上,影響其它整個服務.在複雜的分佈式架構的應用程序有很多的依賴,都會不可避免地在某些時候失敗.高併發的依賴失敗時如果沒有隔離措施,當前應用服務就有被拖垮的風險.
Spring Cloud Netflix Hystrix就是隔離措施的一種實現,可以設置在某種超時或者失敗情形下斷開依賴調用或者返回指定邏輯,從而提高分佈式系統的穩定性.

生活中舉個例子,如電力過載保護器,當電流過大的的時候,出問題,過載器會自動斷開,從而保護電器不受燒壞。因此Hystrix請求熔斷的機制跟電力過載保護器的原理很類似。

比如:訂單系統請求庫存系統,結果一個請求過去,因爲各種原因,網絡超時,在規定幾秒內沒反應,或者服務本身就掛了,這時候更多的請求來了,不斷的請求庫存服務,不斷的創建線程,因爲沒有返回,也就資源沒有釋放,

這也導致了系統資源被耗盡,你的服務奔潰了,這訂單系統好好的,你訪問了一個可能有問題的庫存系統,結果導致你的訂單系統也奔潰了,你再繼續調用更多的依賴服務,可會會導致更多的系統奔潰,這時候Hystrix可以實現快速失敗,

如果它在一段時間內偵測到許多類似的錯誤,會強迫其以後的多個調用快速失敗,不再訪問遠程服務器,從而防止應用程序不斷地嘗試執行可能會失敗的操作進而導致資源耗盡。這時候Hystrix進行FallBack操作來服務降級,

Fallback相當於是降級操作. 對於查詢操作, 我們可以實現一個fallback方法, 當請求後端服務出現異常的時候, 可以使用fallback方法返回的值. fallback方法的返回值一般是設置的默認值或者來自緩存.通知後面的請求告知這服務暫時不可用了。

使得應用程序繼續執行而不用等待修正錯誤,或者浪費CPU時間去等到長時間的超時產生。Hystrix熔斷器也可以使應用程序能夠診斷錯誤是否已經修正,如果已經修正,應用程序會再次嘗試調用操作。

Hystrix設計原則

  1.防止單個服務的故障,耗盡整個系統服務的容器(比如tomcat)的線程資源,避免分佈式環境裏大量級聯失敗。通過第三方客戶端訪問(通常是通過網絡)依賴服務出現失敗、拒絕、超時或短路時執行回退邏輯

   2.用快速失敗代替排隊(每個依賴服務維護一個小的線程池或信號量,當線程池滿或信號量滿,會立即拒絕服務而不會排隊等待)和優雅的服務降級;當依賴服務失效後又恢復正常,快速恢復

   3.提供接近實時的監控和警報,從而能夠快速發現故障和修復。監控信息包括請求成功,失敗(客戶端拋出的異常),超時和線程拒絕。如果訪問依賴服務的錯誤百分比超過閾值,斷路器會跳閘,此時服務會在一段時間內停止對特定服務的所有請求

   4.將所有請求外部系統(或請求依賴服務)封裝到HystrixCommand或HystrixObservableCommand對象中,然後這些請求在一個獨立的線程中執行。使用隔離技術來限制任何一個依賴的失敗對系統的影響。每個依賴服務維護一個小的線程池(或信號量),當線程池滿或信號量滿,會立即拒絕服務而不會排隊等待

Hystrix特性

  1.請求熔斷: 當Hystrix Command請求後端服務失敗數量超過一定比例(默認50%), 斷路器會切換到開路狀態(Open). 這時所有請求會直接失敗而不會發送到後端服務. 斷路器保持在開路狀態一段時間後(默認5秒), 自動切換到半開路狀態(HALF-OPEN).

    這時會判斷下一次請求的返回情況, 如果請求成功, 斷路器切回閉路狀態(CLOSED), 否則重新切換到開路狀態(OPEN). Hystrix的斷路器就像我們家庭電路中的保險絲, 一旦後端服務不可用, 斷路器會直接切斷請求鏈, 避免發送大量無效請求影響系統吞吐量, 並且斷路器有自我檢測並恢復的能力.

  2.服務降級:Fallback相當於是降級操作. 對於查詢操作, 我們可以實現一個fallback方法, 當請求後端服務出現異常的時候, 可以使用fallback方法返回的值. fallback方法的返回值一般是設置的默認值或者來自緩存.告知後面的請求服務不可用了,不要再來了。

  3.依賴隔離(採用艙壁模式,Docker就是艙壁模式的一種):在Hystrix中, 主要通過線程池來實現資源隔離. 通常在使用的時候我們會根據調用的遠程服務劃分出多個線程池.比如說,一個服務調用兩外兩個服務,你如果調用兩個服務都用一個線程池,那麼如果一個服務卡在哪裏,資源沒被釋放

   後面的請求又來了,導致後面的請求都卡在哪裏等待,導致你依賴的A服務把你卡在哪裏,耗盡了資源,也導致了你另外一個B服務也不可用了。這時如果依賴隔離,某一個服務調用A B兩個服務,如果這時我有100個線程可用,我給A服務分配50個,給B服務分配50個,這樣就算A服務掛了,

   我的B服務依然可以用。

  4.請求緩存:比如一個請求過來請求我userId=1的數據,你後面的請求也過來請求同樣的數據,這時我不會繼續走原來的那條請求鏈路了,而是把第一次請求緩存過了,把第一次的請求結果返回給後面的請求。

  5.請求合併:我依賴於某一個服務,我要調用N次,比如說查數據庫的時候,我發了N條請求發了N條SQL然後拿到一堆結果,這時候我們可以把多個請求合併成一個請求,發送一個查詢多條數據的SQL的請求,這樣我們只需查詢一次數據庫,提升了效率。

Hystrixl流程圖如下:

Hystrix流程說明:

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章