Spring Cloud Hystrix java
工做流程圖:緩存
流程說明:併發
1.每次調用建立一個新的HystrixCommand或HystrixObservableCommand把依賴調用封裝在run()方法中.異步
HystrixCommand 用在依賴的服務返回單個操做結果的時候ide
HystrixObservableCommand 用在依賴的服務返回多個操做結果的時候ui
2.執行execute()/queue作同步或異步調用.spa
execute():同步執行,從依賴的服務返回一個單一的結果對象,或是發生錯誤的時候拋出異常線程
@HystrixCommand(fallbackMethod = "helloFallBack") public String helloService() { return restTemplate.getForEntity("http://HELLO-SERVICE/hello", String.class).getBody(); }
queue():異步執行,直接返回一個Future對象,其中包含了服務執行結束時要返回的單一結果對象。3d
@HystrixCommand(fallbackMethod = "helloFallBack") public Future<String> helloServiceAsync() { return new AsyncResult<String>() { @Override public String invoke() { return restTemplate.getForEntity("http://HELLO-SERVICE/hello", String.class).getBody(); } }; }
Future提供的方法:rest
get() 該方法阻塞當前,等待計算完成,獲取返回結果。
isDone () 若是此任務完成返回true
isCancelled() 任務完成前被取消返回true
cancel(false) 取消任務,未開始或已完成返回false,參數表示是否中斷執行中的線程 (true中斷,false不中斷)
3.結果是否被緩存
若當前請求的方法緩存功能時被啓動的,而且該方法命中了緩存,直接返回緩存中的數據
ps:Hystrix中的緩存功能,須要初始化HystrixRequestContext = HystrixRequestContext. initializecontext (),每次發起Request時初始化,須要設置一個Filter。以下源碼中:HystrixRequestContext是ThreadLocal的,也就是說在一次請求中 屢次調用依賴服務 這個時候緩存功能纔有實際意義。若是同時發送兩個請求,也是會調用兩次依賴服務的。
private static ThreadLocal<HystrixRequestContext> requestVariables = new ThreadLocal<HystrixRequestContext>(); public static boolean isCurrentThreadInitialized() { HystrixRequestContext context = requestVariables.get(); return context != null && context.state != null; }
4.判斷熔斷器(circuit-breaker)是否打開,若是打開跳到步驟8,進行降級策略,若是關閉進入第五步驟,檢查是否有可用的資源來執行命令.
判斷斷路器的打開/關閉狀態,詳細邏輯以下:
AtomicBoolean circuitOpen(斷路器是否打開的標識,默認fasle),若是打開標識爲true,標識斷路器是打開狀態,若是打開直接走降級策略fallBack(),不然就從度量指標對象 (HystrixCommandMetrics 用來記錄各種度量指標的對象)中獲取HealthCounts統計對象作進一步判斷(該對象記錄了一個滾動時間窗內的請求信息快照,默認時間窗爲10 S)。
打開熔斷器須要知足下面兩個條件:
1:若是它的請求總數(QPS)在預設的閥值範圍內就返回false,標識熔斷器處於未打開狀態,該閥值的的配置參數爲:hystrix.command.default.circuitBreaker.requestVolumeThreshold=20默認值20
2:若是錯誤百分比在閥值範圍內就返回false,表示斷路器處於未打開狀態,該閥值的配置參數爲:
hystrix.command.default.circuitBreaker.errorThresholdPercentage=50
若是在滾動時間窗內,請求數量超過requestVolumeThreshold的閥值的前提下,若是錯誤請求數的百分比超過50%,就把斷路器設置爲打開狀態,不然就設置爲關閉狀態。
這裏不得不提另外一個參數:hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=5000 默認值5000,該屬性用來設置當斷路器打開以後的休眠時間窗,休眠時間結束後,斷路器置爲「半開」狀態,此時再有請求過來的話,不會直接fallback,並且會嘗試請求命令,若是依然失敗就將斷路器繼續設置爲「打開」的狀態,若是成功斷路器就設置爲「關閉」狀態。
5.判斷線程池/隊列/信號量是否跑滿,若是跑滿進入降級步驟8,不然繼續後續步驟.
、
若是在請求時,hystrix的線程池和請求隊列,或者是信號量(不使用線程池的時候)已經被佔滿的狀況下,Hystrix 也不會執行命令而是轉接到fallback處理。
hystrix指的線程池不是容器的線程池,而是每一個依賴服務的專有線程池,這樣作主要是爲了當某個依賴服務有問題時,不會影響其餘依賴服務,這種模式叫「艙壁模式」。這種模式就和Docker實現進程隔離的模式相同,Docker使得容器和容器直接不會相互影響,而Hystrix則使用該模式實現線程池的隔離。
hystrix線程池隔離的優點:
1:應用自身獲得徹底保護,不會受不可控的依賴服務影響,即使給依賴服務分配的線程池填滿,也不會影響應用自身的其餘部分。
2:能夠有效下降接入新服務的風險,當新服務接入時不穩定或存在問題時,不會影響應用其餘請求、
3:當依賴服務從失效中恢復正常,它的線程池會被清理而且可以立刻恢復健康的服務,比容器級別的清理恢復要快不少。
4:線程池提供內置的併發實現,能夠利用它爲同步的依賴服務構建異步訪問。
示例:
@HystrixCommand(fallbackMethod = "helloFallBack", commandKey = "helloService", groupKey = "Hello", threadPoolKey = "helloServiceIdThread", threadPoolProperties= {@HystrixProperty(name="coreSize",value="20"), @HystrixProperty(name="maxQueueSize",value="10")})
參數說明:coreSize 用來控制核心線程數,也就是最大併發量 默認爲10
maxQueueSize 用來控制隊列大小,當設置爲-1時,線程池將使用SynchronousQueue實現的隊列,不然將使用LinkedBlockingQueue實現的隊列,默認爲-1。
queueSizeRejectionThreshold 該參數用來設置隊列的拒絕閥值,即便隊列沒有達到設置的最大值也能拒絕請求,該參數主要是對LinkedBlockingQueue的補充,由於LinkedBlockingQueue運行時不能動態修改它的大小,而經過該屬性就能夠調整拒絕請求的隊列大小了,默認5。maxQueueSize爲-1時無效,由於maxQueueSize爲-1時,用的是SynchronousQueue,
timeInMilliseconds 該參數用來設置滾動時間窗的長度,單位爲毫秒。該滾動時間窗的長度用於線程池的指標度量,它會被分紅多個桶進行統計。默認10000
numBuckets 該參數用來設置滾動時間窗被劃爲成「桶」的數量,默認10
6.調用HystrixCommand的run方法.運行依賴邏輯 依賴邏輯調用超時,進入步驟8.
配置參數:
execution配置控制的是HystrixCommand.run()的執行
execution.isolation.strategy: 該屬性用來設置執行的隔離策略。 1:Thread 線程 2:Semaphore 信號量 ,默認Thread
execution.isolation.thread.timeoutInMilliseconds:該屬性用來配置HystrixCommand執行的超時間,若是超時直接進入fallBack,並將命令標記爲TIMEOUT 默認值1000毫秒
execution.timeOut.enabled:該屬性用來配置是否啓用超時設置,當設置爲false時execution.isolation.thread.timeoutInMilliseconds將不起做用。默認爲true
execution.isolation.thread.interruptOntimeout:該屬性用來配置當HstrixCommand.run()執行超時是否要將它中斷
execution.isolation.thread.interruptOnCancel:該屬性用來配置當HystrixCommand.run()執行被取消時是否要將它中斷
execution.isolation.semaphore.maxConcurrentRequests:當HystrixCommand的隔離策略使用信號量時,用來設置信號量的大小(併發請求數)。當最大的併發數到達閥值時,後續的請求都會被拒絕,默認值10
7.判斷邏輯是否調用成功。返回成功調用結果;調用出錯,進入步驟8fallback.
判斷調用成功主要就是看是否超時,是否拋出異常,這裏要說的時若是設置了忽略異常,當異常類型是ClassCastException時 是不會觸發fallback的,會將異常信息包裝在HystrixBadRequestException中拋出。
@HystrixCommand(fallbackMethod = "helloFallBack", ignoreExceptions = ClassCastException.class)
8.計算熔斷器狀態,全部的運行狀態(成功, 失敗, 拒絕,超時)上報給熔斷器,用於統計從而判斷熔斷器狀態.
9.getFallback()降級邏輯。如下四種狀況將觸發getFallback調用:
沒有實現getFallback的Command將直接拋出異常,fallback降級邏輯調用成功直接返回,降級邏輯調用失敗拋出異常.
10.返回執行成功結果
Name |
Description |
Triggers Fallback? |
---|---|---|
執行失敗 | 拋出異常 | YES |
超時 | 開始執行,但沒有在容許的時間內完成 | YES |
斷路器 | 斷路器打開狀態下 | YES |
線程池拒絕 | 線程池的容量滿了或大於拒絕閥值 | YES |
信號量拒絕 | 信號量容量滿了 | YES |
任務執行失敗,執行超時,依賴熔斷,執行線程池滿,信號量滿會fullback
熔斷器實現三種類型的狀態:open、half-open以及closed:
熔斷執行流程:
當熔斷器開關打開時, 請求被禁止經過.
熔斷器開關處於打開狀態, 通過一段時間後, 熔斷器會自動進入半開狀態, 這時熔斷器只容許一個請求經過. 當該請求調用成功時, 熔斷器恢復;失敗,將繼續保持熔斷狀態
自動熔斷機制