天天看點

Spring Cloud中Hystrix、Ribbon及Feign的熔斷關系是什麼?

Spring Cloud中Hystrix、Ribbon及Feign的熔斷關系是什麼?

導讀

今天和大家聊一聊在Spring Cloud微服務架構實踐中,比較核心但是又很容易把人搞得稀裡糊塗的一個問題,那就是在Spring Cloud中Hystrix、Ribbon以及Feign它們三者之間在處理微服務調用逾時進而觸發熔斷降級的關系是什麼?

我們知道在Spring Cloud微服務體系下,微服務之間的互相調用可以通過Feign進行聲明式調用,在這個服務調用過程中Feign會通過Ribbon從服務注冊中心擷取目标微服務的伺服器位址清單,之後在網絡請求的過程中Ribbon就會将請求以負載均衡的方式打到微服務的不同執行個體上,進而實作Spring Cloud微服務架構中最為關鍵的功能即服務發現及用戶端負載均衡調用。

另一方面微服務在互相調用的過程中,為了防止某個微服務的故障消耗掉整個系統所有微服務的連接配接資源,是以在實施微服務調用的過程中我們會要求在調用方實施針對被調用微服務的熔斷邏輯。而要實作這個邏輯場景在Spring Cloud微服務架構下我們是通過Hystrix這個架構來實作的。

調用方會針對被調用微服務設定調用逾時時間,一旦逾時就會進入熔斷邏輯,而這個故障名額資訊也會傳回給Hystrix元件,Hystrix元件會根據熔斷情況判斷被調微服務的故障情況進而打開熔斷器,之後所有針對該微服務的請求就會直接進入熔斷邏輯,直到被調微服務故障恢複,Hystrix斷路器關閉為止。

Hystrix、Feign及Ribbon的配置說明

接下來我們先來看看在Spring Cloud微服務系統中Hystrix、Feign及Ribbon的常用配置都有哪些以及它們的使用場景分别是什麼?

Hystrix配置說明

在Spring Cloud微服務體系中Hystrix主要被用于實作實作微服務之間網絡調用故障的熔斷、過載保護及資源隔離等功能。而要正确使用Hystrix提供的這些功能就需要對Hystrix常用的配置有一定深入的了解,否則你會發現使用過程中認為一定會生效的配置常常不會起作用,接下來我們就按照參數配置的類型對Hystrix中的常見配置做一個梳理。

1)、線程隔離相關配置

Hystrix具備的重要關鍵特性之一就是它能夠實作對第三方服務依賴的資源隔離,而隔離最常見的方式是通過線程池資源的隔離來實作的,Hystrix會為每個第三方服務依賴配置單獨的線程池資源,進而避免對第三方服務依賴的請求占用應用主線程資源以免造成系統雪崩。Hystrix中關于線程隔離相關的配置如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

hystrix:

command:

#全局預設配置
default:
  #線程隔離相關
  execution:
    timeout:
      #是否給方法執行設定逾時時間,預設為true。一般我們不要改。
      enabled: true
    isolation:
      #配置請求隔離的方式,這裡是預設的線程池方式。還有一種信号量的方式semaphore,使用比較少。
      strategy: threadPool
      thread:
        #方式執行的逾時時間,預設為1000毫秒,在實際場景中需要根據情況設定
        timeoutInMilliseconds: 1000
        #發生逾時時是否中斷方法的執行,預設值為true。不要改。
        interruptOnTimeout: true
        #是否在方法執行被取消時中斷方法,預設值為false。沒有實際意義,預設就好!
        interruptOnCancel: false           

  

2)、熔斷器相關配置

熔斷器是Hystrix最主要的功能,它開啟和關閉的時機、靈敏度及準确性是Hystrix是否能夠發揮重要的關鍵,而在Hystrix中與熔斷器相關的幾個配置如下:

20

21

22

23

24

#全局預設配置
default:
  #熔斷器相關配置
  circuitBreaker:
    #說明:是否啟動熔斷器,預設為true。我們使用Hystrix的目的就是為了熔斷器,不要改,否則就不要引入Hystrix。
    enabled: true
    #說明1:啟用熔斷器功能視窗時間内的最小請求數,假設我們設定的視窗時間為10秒,
    #說明2:那麼如果此時預設值為20的話,那麼即便10秒内有19個請求都失敗也不會打開熔斷器。
    #說明3:此配置項需要根據接口的QPS進行計算,值太小會有誤打開熔斷器的可能,而如果值太大超出了時間視窗内的總請求數,則熔斷永遠也不會被觸發
    #說明4:建議設定一般為:QPS*視窗描述*60%
    requestVolumeThreshold: 20
    #說明1:熔斷器被打開後,所有的請求都會被快速失敗掉,但是何時恢複服務是一個問題。熔斷器打開後,Hystrix會在經過一段時間後就放行一條請求
    #說明2:如果請求能夠執行成功,則說明此時服務可能已經恢複了正常,那麼熔斷器會關閉;相反執行失敗,則認為服務仍然不可用,熔斷器保持打開。
    #說明3:是以此配置的作用是指定熔斷器打開後多長時間内允許一次請求嘗試執行,官方預設配置為5秒。
    sleepWindowInMilliseconds: 5000
    #說明1:該配置是指在通過滑動視窗擷取到目前時間段内Hystrix方法執行失敗的幾率後,根據此配置來判斷是否需要打開熔斷器
    #說明2:這裡官方的預設配置為50,即視窗時間内超過50%的請求失敗後就會打開熔斷器将後續請求快速失敗掉
    errorThresholdPercentage: 50
    #說明:是否強制啟用熔斷器,預設false,沒有什麼場景需要這麼配置,忽略!
    forceOpen: false
    #說明:是否強制關閉熔斷器,預設false,沒有什麼場景需要這麼配置,忽略!
    forceClosed: false           

3)、Metrics(統計器)相關配置

Hystrix是否正常工作最主要的依賴就是根據捕獲的調用名額資訊來判斷是否打開或者關閉熔斷器,而影響Hystrix行為很重要的因素就是以下Hystrix關于Metrics的配置。

25

26

27

28

29

30

31

32

#全局預設配置
default:
  metrics:
    rollingStats:
      #說明:此配置用于設定Hystrix統計滑動視窗的時間,機關為毫秒,預設設定為10000毫秒,即一個滑動視窗預設統計的是10秒内的請求資料。
      timeInMilliseconds: 10000
      #說明2:此屬性指定了滑動統計視窗劃分的桶數。預設為10。
      #說明2:需要注意的是,metrics.rollingStats.timeInMilliseconds % metrics.rollingStats.numBuckets == 0必須成立,否則就會抛出異常
      numBuckets: 10

    rollingPercentile:
      #說明1:此屬性配置統計方法是否響應時間百分比,預設為true。
      #說明2:Hystrix會統計方法執行1%,10%,50%,90%,99%等比例請求的平均耗時用來生成統計圖表。
      #說明3:如果禁用該參數設定false,那麼所有彙總統計資訊(平均值、百分位數)将傳回-1。
      enabled: true
      #說明:統計響應時間百分比時的視窗大小,預設為60000毫秒,即1分鐘
      timeInMilliseconds: 60000
      #說明1:此屬性用于設定滑動百分比視窗要劃分的桶數,預設為6。
      #說明2:需要注意的是,metrics.rollingPercentile.timeInMilliseconds % metrics.rollingPercentile.numBuckets == 0必須成立,否則會抛出異常
      numBuckets: 6
      #說明1:該屬性表示統計響應時間百分比,每個滑動視窗的桶内要儲存的請求數,預設為100。
      #說明2:即預設10秒的桶内,如果執行了500次請求,那麼隻有最後100次請求執行的資訊會被儲存到桶内。
      #說明3:增加這個值會增加記憶體消耗量,一般情況下無需更改。
      bucketSize: 100

    healthSnapshot:
      #說明1:該參數配置了健康資料統計器(會影響Hystrix熔斷)中每個桶的大小,預設為500毫秒。
      #說明2:在統計時Hystrix通過metrics.rollingStats.timeInMilliseconds / metrics.healthSnapshot.intervalInMilliseconds計算出桶數。
      #說明3:在視窗滑動時,每滑過一個桶的時間就統計一次目前視窗内請求的失敗率。
      intervalInMilliseconds: 500           

在上述關于Metrics的配置中出現了兩個比較頻繁的概念:滑動視窗、桶,Hystrix的統計器就是由滑動視窗來實作的。關于滑動視窗舉一個非常形象的例子,假設你坐在一輛大巴車的上,車窗外是一排排筆直的大樹,車輛在高速地行駛着,大樹迅速地從車窗滑過,如果用每棵樹來代表一個網絡請求,用大巴車的行駛代表時間的流逝。那麼大巴車的視窗就是一個非常典型的滑動視窗,而你通過這個車窗能夠看到的大樹就是Hystrix要統計的資料。

桶(bucket)是Hystrix統計滑動視窗資料時的最小機關。同樣以上面的例子為例,在大巴車行駛非常快的情況下,如果每掠過一棵樹就統計一次視窗内大樹的資料的話,會造成比較大的開銷,而如果我們将車窗分成10份,大巴車行駛時每掠過視窗的1/10就統計一次資料,那麼開銷就會小很多了。是以,Hystrix中的桶就是滑動視窗1/N的概念。

4)、線程池相關配置

在前面提到過Hystrix實作對第三方服務依賴資源隔離最主要的方式就是通過線程池,而Hystrix内線程的使用是基于Java内置線程池的簡單封裝,通過以下Hystrix線程池參數我們可以控制執行Hystrix指令的線程池的行為。具體如下:

default:
  #說明:核心線程池的大小,預設值是10
  coreSize: 10
  #說明:是否允許線程池擴充到最大線程池數量,預設為false。
  allowMaximumSizeToDivergeFromCoreSize: false
  #說明:線程池中線程的最大數量,預設值是10。此配置項單獨配置時并不會生效,需要啟用allowMaximumSizeToDivergeFromCoreSize
  maximumSize: 10
  #說明1:作業隊列的最大值,預設值為-1。表示隊列會使用SynchronousQueue,此時值為0,Hystrix不會向隊列記憶體放作業。
  #說明2:如果此值設定為一個正int型,隊列會使用一個固定size的LinkedBlockingQueue,此時在核心線程池都忙碌的情況下,會将作業暫時存放在此隊列内,但是超出此隊列的請求依然會被拒絕
  maxQueueSize: -1
  #設定隊列拒絕請求的閥值,預設為5。
  queueSizeRejectionThreshold: 5
  #控制線程在釋放前未使用的時間,預設為1分鐘。
  keepAliveTimeMinutes: 1           

Ribbon配置說明

Ribbon在Spring Cloud中對于支援微服之間的通信發揮着非常關鍵的作用,其主要功能包括用戶端負載均衡器及用于中間層通信的用戶端。在基于Feign的微服務通信中無論是否開啟Hystrix,Ribbon都是必不可少的,Ribbon的配置參數主要如下:

ribbon:

#說明:同一台執行個體的最大自動重試次數,預設為1次,不包括首次

MaxAutoRetries: 1

#說明:要重試的下一個執行個體的最大數量,預設為1,不包括第一次被調用的執行個體

MaxAutoRetriesNextServer: 1

#說明:是否所有的操作都重試,預設為true

OkToRetryOnAllOperations: true

#說明:從注冊中心重新整理伺服器清單資訊的時間間隔,預設為2000毫秒,即2秒

ServerListRefreshInterval: 2000

#說明:使用Apache HttpClient連接配接逾時時間,機關為毫秒

ConnectTimeout: 3000

#說明:使用Apache HttpClient讀取的逾時時間,機關為毫秒

ReadTimeout: 3000

#說明:初始伺服器清單,不需要手工配置,在運作時動态根據注冊中心更新

listOfServers: www.microsoft.com:80,www.yahoo.com:80,www.google.com:80

以上配置方式将對所有的微服務調用有效,如果想針對單獨的微服務進行配置,使用“微服務名.ribbon”這樣的配置方式即可,例如:

bike:

ribbon:

ReadTimeout: 30000           

operation:

ReadTimeout: 30000           

Feign配置說明

Feign是一款Java語言編寫的HttpClient綁定器,在Spring Cloud微服務中用于實作微服務之間的聲明式調用,Feign自身可以支援多種HttpClient工具包,例如OkHttp及Apache HttpClient,針對不同的HttpClient其預設常見配置如下:

feign:

hystrix:

enabled: true           

client:

config:
  #JDK預設HttpURLConnection 實作的 Http Client配置
  default:
    #連接配接逾時時間
    connectTimeout: 5000
    #讀取逾時時間
    readTimeout: 5000
    #錯誤解碼器
    errorDecoder: com.wudimanong.client.common.FeignClientErrorDecoder
    #解碼器
    encoder: com.wudimanong.client.common.FeignClientEncoder
    #編碼器
    decoder: com.wudimanong.client.common.FeignClientDecoder           

Feign、Hystrix、Ribbon的逾時配置關系

在前面的内容我們分别單獨梳理了Feign、Hystrix及Ribbon三者常見的配置,針對各自的特性功能配置我們并沒有異議,但是我們也看到它們都有針對微服務逾時的配置,而在開啟熔斷器功能後,這些逾時配置會影響到熔斷器及服務降級邏輯的行為,那麼它們之間逾時的配置有什麼關系呢?如下:

如上圖所示,在Spring Cloud中使用Feign進行微服務調用分為兩層:Ribbon的調用及Hystrix的調用。是以Feign的逾時時間就是Ribbon和Hystrix逾時時間的結合,而如果不啟用Hystrix則Ribbon的逾時時間就是Feign的逾時時間配置,Feign自身的配置會被覆寫。

而如果開啟了Hystrix,那麼Ribbon的逾時時間配置與Hystrix的逾時時間配置則存在依賴關系,因為涉及到Ribbon的重試機制,是以一般情況下都是Ribbon的逾時時間小于Hystrix的逾時時間,否則會出現以下錯誤:

2019-07-12 11:10:20,238 397194 [http-nio-8084-exec-2] WARN o.s.c.n.z.f.r.s.AbstractRibbonCommand - The Hystrix timeout of 40000ms for the command operation is set lower than the combination of the Ribbon read and connect timeout, 80000ms.

那麼Ribbon和Hystrix的逾時時間配置的關系具體是什麼呢?如下:

Hystrix的逾時時間=Ribbon的重試次數(包含首次)*(ribbon.ReadTimeout+ribbon.ConnectTimeout)

而Ribbon的重試次數的計算方式為:

Ribbon重試次數(包含首次)=1+ribbon.MaxAutoRetries+ribbon.MaxAutoRetriesNextServer+(ribbon.MaxAutoRetries*ribbon.MaxAutoRetriesNextServer)

以上圖中的Ribbon配置為例子,Ribbon的重試次數=1+(1+1+1)*(30000+10000),是以Hystrix的逾時配置應該>=160000毫秒。在Ribbon逾時但Hystrix沒有逾時的情況下,Ribbon便會采取重試機制;而重試期間如果時間超過了Hystrix的逾時配置則會立即被熔斷(fallback)。

如果不配置Ribbon的重試次數,則Ribbon預設會重試一次,加上第一次調用Ribbon的重試次數為2次,以上述配置為例Hystrix逾時時間配置為2*40000=80000,由于很多情況下,大家一般不會主動配置Ribbon的重試次數,是以這裡需要注意下!強調下,以上逾時配置的值隻是示範,逾時配置有點大不太合适實際的線上場景,大家根據實際情況設定即可!

原文位址

https://www.cnblogs.com/wudimanong/p/11224494.html