雪崩效應:是一種因服務提供者的不可用致使服務調用者的不可用,並將不可用逐漸放大的過程java
正常狀況下的服務:git
某一服務出現異常,拖垮整個服務鏈路,消耗整個線程隊列,形成服務不可用,資源耗盡:github
a)硬件故障:硬件損壞形成的服務器主機宕機, 網絡硬件故障形成的服務提供者的不可訪問segmentfault
b)程序Bug:後端
c) 緩存擊穿:緩存擊穿通常發生在緩存應用重啓, 全部緩存被清空時,以及短期內大量緩存失效時. 大量的緩存不命中, 使請求直擊後端,形成服務提供者超負荷運行,引發服務不可用緩存
d)用戶大量請求:在秒殺和大促開始前,若是準備不充分,用戶發起大量請求也會形成服務提供者的不可用服務器
a)用戶重試:在服務提供者不可用後, 用戶因爲忍受不了界面上長時間的等待,而不斷刷新頁面甚至提交表單網絡
b)代碼邏輯重試: 服務調用端的會存在大量服務異常後的重試邏輯併發
a)同步等待形成的資源耗盡:當服務調用者使用同步調用 時, 會產生大量的等待線程佔用系統資源. 一旦線程資源被耗盡,服務調用者提供的服務也將處於不可用狀態, 因而服務雪崩效應產生了。app
Hystrix 是一個幫助解決分佈式系統交互時超時處理和容錯的類庫, 它一樣擁有保護系統的能力。Netflix的衆多開源項目之一。
1. 隔離:
Hystrix隔離方式採用線程/信號的方式,經過隔離限制依賴的併發量和阻塞擴散
1)線程隔離
Hystrix在用戶請求和服務之間加入了線程池。
Hystrix爲每一個依賴調用分配一個小的線程池,若是線程池已滿調用將被當即拒絕,默認不採用排隊.加速失敗斷定時間。線程數是能夠被設定的。
原理:用戶的請求將再也不直接訪問服務,而是經過線程池中的空閒線程來訪問服務,若是線程池已滿,則會進行降級處理,用戶的請求不會被阻塞,至少能夠看到一個執行結果(例如返回友好的提示信息),而不是無休止的等待或者看到系統崩潰。
隔離前:
隔離後:
b)信號隔離:
信號隔離也能夠用於限制併發訪問,防止阻塞擴散, 與線程隔離最大不一樣在於執行依賴代碼的線程依然是請求線程(該線程須要經過信號申請, 若是客戶端是可信的且能夠快速返回,可使用信號隔離替換線程隔離,下降開銷。信號量的大小能夠動態調整, 線程池大小不能夠。(參考文章2)
2. 熔斷:
若是某個目標服務調用慢或者有大量超時,此時,熔斷該服務的調用,對於後續調用請求,不在繼續調用目標服務,直接返回,快速釋放資源。若是目標服務狀況好轉則恢復調用。
熔斷器:Circuit Breaker
熔斷器是位於線程池以前的組件。用戶請求某一服務以後,Hystrix會先通過熔斷器,此時若是熔斷器的狀態是打開(跳起),則說明已經熔斷,這時將直接進行降級處理,不會繼續將請求發到線程池。熔斷器至關於在線程池以前的一層屏障。每一個熔斷器默認維護10個bucket ,每秒建立一個bucket ,每一個blucket記錄成功,失敗,超時,拒絕的次數。當有新的bucket被建立時,最舊的bucket會被拋棄。
熔斷器的狀態機:
流程說明:
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
:返回執行成功結果
同步執行:即一旦開始執行該命令,當前線程就得阻塞着直到該命令返回結果,而後才能繼續執行下面的邏輯
異步執行:命令開始執行會返回一個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。
jar包:
<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模式:
|
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 |
7、參考文章
官方文檔:https://github.com/Netflix/Hystrix/wiki
同步異步反應執行三種方式示例:Hystrix使用&設置準則#2.使用
http://mvnrepository.com/artifact/com.netflix.hystrix/hystrix-javanica