熔斷機制hystrix

1、問題產生

雪崩效應:是一種因服務提供者的不可用致使服務調用者的不可用,並將不可用逐漸放大的過程java

  正常狀況下的服務git

某一服務出現異常,拖垮整個服務鏈路,消耗整個線程隊列,形成服務不可用,資源耗盡:github

    

     造成過程:

           1)服務提供者不可用    

                             a)硬件故障:硬件損壞形成的服務器主機宕機, 網絡硬件故障形成的服務提供者的不可訪問segmentfault

                             b)程序Bug:後端

                             c)   緩存擊穿:緩存擊穿通常發生在緩存應用重啓, 全部緩存被清空時,以及短期內大量緩存失效時. 大量的緩存不命中, 使請求直擊後端,形成服務提供者超負荷運行,引發服務不可用緩存

                             d)用戶大量請求:在秒殺和大促開始前,若是準備不充分,用戶發起大量請求也會形成服務提供者的不可用服務器

           2)重試加大流量

                             a)用戶重試:在服務提供者不可用後, 用戶因爲忍受不了界面上長時間的等待,而不斷刷新頁面甚至提交表單網絡

                             b)代碼邏輯重試: 服務調用端的會存在大量服務異常後的重試邏輯併發

           3)服務調用者不可用

                         a)同步等待形成的資源耗盡:當服務調用者使用同步調用 時, 會產生大量的等待線程佔用系統資源. 一旦線程資源被耗盡,服務調用者提供的服務也將處於不可用狀態, 因而服務雪崩效應產生了。app

2、概念

  1. 服務熔斷
              通常是指軟件系統中,因爲某些緣由使得服務出現了過載現象,爲防止形成整個系統故障,從而採用的一種保護措施,因此不少地方把熔斷亦稱爲過載保護。不少時候剛開始可能只是系統出現了局部的、小規模的故障,然而因爲種種緣由,故障影響的範圍愈來愈大,最終致使了全局性的後果。
    適用場景:防止應用程序直接調用那些極可能會調用失敗的遠程服務或共享資源
  2. 服務降級:
              當服務器壓力劇增的狀況下,根據當前業務狀況及流量對一些服務和頁面有策略的降級,以此釋放服務器資源以保證核心任務的正常運行。

3、工做原理

       Hystrix 是一個幫助解決分佈式系統交互時超時處理和容錯的類庫, 它一樣擁有保護系統的能力。Netflix的衆多開源項目之一。

     1. 隔離

           Hystrix隔離方式採用線程/信號的方式,經過隔離限制依賴的併發量和阻塞擴散

            1)線程隔離

            Hystrix在用戶請求和服務之間加入了線程池。

            Hystrix爲每一個依賴調用分配一個小的線程池,若是線程池已滿調用將被當即拒絕,默認不採用排隊.加速失敗斷定時間。線程數是能夠被設定的。

            原理:用戶的請求將再也不直接訪問服務,而是經過線程池中的空閒線程來訪問服務,若是線程池已滿,則會進行降級處理,用戶的請求不會被阻塞,至少能夠看到一個執行結果(例如返回友好的提示信息),而不是無休止的等待或者看到系統崩潰。

隔離前:

            

     

 

隔離後:

     b)信號隔離:

         信號隔離也能夠用於限制併發訪問,防止阻塞擴散, 與線程隔離最大不一樣在於執行依賴代碼的線程依然是請求線程(該線程須要經過信號申請, 若是客戶端是可信的且能夠快速返回,可使用信號隔離替換線程隔離,下降開銷。信號量的大小能夠動態調整, 線程池大小不能夠。(參考文章2)

 

     2. 熔斷

若是某個目標服務調用慢或者有大量超時,此時,熔斷該服務的調用,對於後續調用請求,不在繼續調用目標服務,直接返回,快速釋放資源。若是目標服務狀況好轉則恢復調用。

熔斷器:Circuit Breaker

      熔斷器是位於線程池以前的組件。用戶請求某一服務以後,Hystrix會先通過熔斷器,此時若是熔斷器的狀態是打開(跳起),則說明已經熔斷,這時將直接進行降級處理,不會繼續將請求發到線程池熔斷器至關於在線程池以前的一層屏障。每一個熔斷器默認維護10個bucket ,每秒建立一個bucket ,每一個blucket記錄成功,失敗,超時,拒絕的次數。當有新的bucket被建立時,最舊的bucket會被拋棄。

         熔斷器的狀態機:

           

  • Closed:熔斷器關閉狀態,調用失敗次數積累,到了閾值(或必定比例)則啓動熔斷機制;
  • Open:熔斷器打開狀態,此時對下游的調用都內部直接返回錯誤,不走網絡,但設計了一個時鐘選項,默認的時鐘達到了必定時間(這個時間通常設置成平均故障處理時間,也就是MTTR),到了這個時間,進入半熔斷狀態;
  • Half-Open:半熔斷狀態,容許定量的服務請求,若是調用都成功(或必定比例)則認爲恢復了,關閉熔斷器,不然認爲還沒好,又回到熔斷器打開狀態; 

4、流程

流程說明:
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 :返回執行成功結果

5、執行方式

同步執行:即一旦開始執行該命令,當前線程就得阻塞着直到該命令返回結果,而後才能繼續執行下面的邏輯

異步執行:命令開始執行會返回一個Future<T>的對象,不阻塞後面的邏輯,開發者本身根據須要去獲取結果。

響應式執行:命令開始執行會返回一個Observable<T> 對象,開發者能夠給給Obeservable對象註冊上Observer或者Action1對象,響應式地處理命令執行過程當中的不一樣階段。當調用HystrixCommand的observe()方法,或使用Observable的工廠方法(just(),from())即爲響應式執行,這個功能的實現是基於Netflix的另外一個開源項目RxJava(https://github.com/Netflix/RxJava)來的,更細節的用法能夠參考:https://github.com/Netflix/Hystrix/wiki/How-To-Use#wiki-Reactive-Execution

6、代碼實現

jar包:

hystrix包
<dependency>
     <groupId>com.netflix.hystrix</groupId>
     <artifactId>hystrix-core</artifactId>
     <version> 1.4 . 21 </version>
</dependency>
設置參數  展開原碼

 

參數
做用
備註

circuitBreaker.errorThresholdPercentage

失敗率達到多少百分比後熔斷

默認值:50

主要根據依賴重要性進行調整

circuitBreaker.forceClosed

是否強制關閉熔斷 若是是強依賴,應該設置爲true

circuitBreaker.requestVolumeThreshold

熔斷觸發的最小個數/10s 默認值:20

circuitBreaker.sleepWindowInMilliseconds

熔斷多少秒後去嘗試請求 默認值:5000

commandKey

  默認值:當前執行方法名

coreSize

線程池coreSize

默認值:10

execution.isolation.semaphore.maxConcurrentRequests

信號量最大併發度 SEMAPHORE模式有效,默認值:10

execution.isolation.strategy

隔離策略,有THREAD和SEMAPHORE

默認使用THREAD模式,如下幾種可使用SEMAPHORE模式:

  • 只想控制併發度
  • 外部的方法已經作了線程隔離
  • 調用的是本地方法或者可靠度很是高、耗時特別小的方法(如medis)

execution.isolation.thread.interruptOnTimeout

是否打開超時線程中斷 THREAD模式有效

execution.isolation.thread.timeoutInMilliseconds

 

超時時間

默認值:1000

在THREAD模式下,達到超時時間,能夠中斷

在SEMAPHORE模式下,會等待執行完成後,再去判斷是否超時

execution.timeout.enabled

是否打開超時  

fallback.isolation.semaphore.maxConcurrentRequests

fallback最大併發度 默認值:10

groupKey

表示所屬的group,一個group共用線程池

默認值:getClass().getSimpleName();

maxQueueSize

請求等待隊列

默認值:-1

若是使用正數,隊列將從SynchronizeQueue改成LinkedBlockingQueue

hystrix.command.default.metrics.rollingStats.timeInMilliseconds  設置統計的時間窗口值的,毫秒值 circuit break 的打開會根據1個rolling window的統計來計算。若rolling window被設爲10000毫秒,則rolling window會被分紅n個buckets,每一個bucket包含success,failure,timeout,rejection的次數的統計信息。默認10000
hystrix.command.default.metrics.rollingStats.numBuckets  設置一個rolling window被劃分的數量  
hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds  記錄health 快照(用來統計成功和錯誤綠)的間隔,默認500ms  

 

 展開原碼
監控service  展開原碼
同步執行  展開原碼
異步執行  展開原碼

 

7、參考文章

 官方文檔:https://github.com/Netflix/Hystrix/wiki

使用Hystrix實現自動降級與依賴隔離

同步異步反應執行三種方式示例:Hystrix使用&設置準則#2.使用

http://mvnrepository.com/artifact/com.netflix.hystrix/hystrix-javanica

http://blog.csdn.net/guwei9111986/article/details/51649240

http://www.javashuo.com/article/p-augpkylg-kt.html

相關文章
相關標籤/搜索