Spring Cloud Hystrix 服務容錯保護詳解

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調用:

  • run()方法拋出非HystrixBadRequestException異常。
  • run()方法調用超時
  • 熔斷器開啓攔截調用
  • 線程池/隊列/信號量是否跑滿

沒有實現getFallback的Command將直接拋出異常,fallback降級邏輯調用成功直接返回,降級邏輯調用失敗拋出異常.

10.返回執行成功結果

 

fallback條件

Name

Description

Triggers Fallback?

執行失敗 拋出異常 YES
超時 開始執行,但沒有在容許的時間內完成 YES
斷路器 斷路器打開狀態下 YES
線程池拒絕 線程池的容量滿了或大於拒絕閥值 YES
信號量拒絕 信號量容量滿了 YES

 

任務執行失敗,執行超時,依賴熔斷,執行線程池滿,信號量滿會fullback

 

熔斷條件

 

熔斷器實現三種類型的狀態:open、half-open以及closed:

 

熔斷執行流程:

 

  • 熔斷器開關關閉時, 請求被容許經過熔斷器. 若是當前健康情況高於設定閾值, 開關繼續保持關閉. 若是當前健康情況低於設定閾值, 開關則切換爲打開狀態.
  • 當熔斷器開關打開時, 請求被禁止經過.

  • 熔斷器開關處於打開狀態, 通過一段時間後, 熔斷器會自動進入半開狀態, 這時熔斷器只容許一個請求經過. 當該請求調用成功時, 熔斷器恢復;失敗,將繼續保持熔斷狀態

自動熔斷機制

  1. 當外部依賴I訪問出錯比例達到某個閾值時,自動觸發熔斷,以後一小段時間duration(可配置)內訪問I的請求自動被降級處理,再也不發給A
  2. 過了設定的duration時間後,放過一個請求到依賴I,探測是否恢復正常,若是恢復正常,解除熔斷,不然繼續保持通訊熔斷狀態。
相關文章
相關標籤/搜索