Hystrix-資源隔離策略(線程、信號量)


1.為什么要進行資源隔離

        比如我們現在有3個業務調用分別是查詢訂單、查詢商品、查詢用戶,且這三個業務請求都是依賴第三方服務-訂單服務、商品服務、用戶服務。三個服務均是通過RPC調用。當依賴的訂單服務變慢了,而這個時候后續有大量的查詢訂單請求過來,那么容器中的線程數量則會持續增加直致CPU資源耗盡到100%,整個服務對外不可用,集群環境下就是雪崩。所以,有必要將多個依賴服務的調用分別隔離到各自自己的資源池內,不對其他服務造成影響。如下圖:

2. 兩種隔離方式  

  Hystrix的隔離策略有兩種:分別是線程隔離和信號量隔離。

  THREAD(線程隔離):使用該方式,HystrixCommand將會在單獨的線程上執行,並發請求受線程池中線程數量的限制。
  SEMAPHORE(信號量隔離):使用該方式,HystrixCommand將會在調用線程上執行,開銷相對較小,並發請求受信號量的個數的限制。

  配置:hystrix.command.default.execution.isolation.strategy 隔離策略,默認是Thread, 可選Thread|Semaphore

2.1 線程隔離(THREAD)

        適用場景:適合絕大多數的場景,對依賴服務的網絡調用timeout,TPS要求高的這種問題
        執行依賴代碼的線程與請求線程(比如Tomcat線程)分離,請求線程可以自由控制離開的時間,這也是我們通常說的異步編程,Hystrix是結合RxJava來實現的異步編程。通過為每個包裹了HystrixCommand的API接口設置獨立的、固定大小的線程池(hystrix.threadpool.default.coreSize)來控制並發訪問量,當線程飽和的時候可以拒絕服務(走fallback方法),防止依賴問題擴散。
        線上建議線程池不要設置過大,否則大量堵塞線程有可能會拖慢服務器。

 2.1.1 線程池隔離的優缺點

優點:
    一個依賴調用可以給予一個線程池,這個依賴的異常不會影響其他的依賴。
    使用線程可以完全隔離業務代碼,請求線程可以快速返回。
    可以完全模擬異步調用,方便異步編程。

缺點:
    使用線程池的缺點主要是增加了計算的開銷。每一個依賴調用都會涉及到隊列,調度,上下文切換,而這些操作都有可能在不同的線程中執行。

2.1.2 線程池隔離相關參數

  讓我們來逐個介紹下@HystrixCommand注解的各個參數:
  1:commandKey:配置全局唯一標識服務的名稱,比如,庫存系統有一個獲取庫存服務,那么就可以為這個服務起一個名字來唯一識別該服務,如果不配置,則默認是@HystrixCommand注解修飾的函數的函數名。


  2:groupKey:一個比較重要的注解,配置全局唯一標識服務分組的名稱,比如,庫存系統就是一個服務分組。通過設置分組,Hystrix會根據組來組織和統計命令的告、儀表盤等信息。Hystrix命令默認的線程划分也是根據命令組來實現。默認情況下,Hystrix會讓相同組名的命令使用同一個線程池,所以我們需要在創建Hystrix命令時為其指定命令組來實現默認的線程池划分。此外,Hystrix還提供了通過設置threadPoolKey來對線程池進行設置。建議最好設置該參數,使用threadPoolKey來控制線程池組。

  例如有如下代碼:

 dashboard為

 說明:

findById - HystrixCommandKey(默認為Controller下的方法名)
MovieController - HystrixThreadPoolKey(不配置的情況下就是commandGroupKey,HystrixCommandGroupKey默認為類名)

  3:threadPoolKey:對線程池進行設定,細粒度的配置,相當於對單個服務的線程池信息進行設置,也可多個服務設置同一個threadPoolKey構成線程組。

  4:fallbackMethod:@HystrixCommand注解修飾的函數的回調函數,@HystrixCommand修飾的函數必須和這個回調函數定義在同一個類中,因為定義在了同一個類中,所以fackback method可以是public/private均可。

  5:commandProperties:配置該命令的一些參數,如executionIsolationStrategy配置執行隔離策略,默認是使用線程隔離,此處我們配置為THREAD,即線程池隔離。參見:com.netflix.hystrix.HystrixCommandProperties中各個參數的定義。

  6:threadPoolProperties:線程池相關參數設置,具體可以設置哪些參數請見:com.netflix.hystrix.HystrixThreadPoolProperties

  7:ignoreExceptions:調用服務時,除了HystrixBadRequestException之外,其他@HystrixCommand修飾的函數拋出的異常均會被Hystrix認為命令執行失敗而觸發服務降級的處理邏輯(調用fallbackMethod指定的回調函數),所以當需要在命令執行中拋出不觸發降級的異常時來使用它,通過這個參數指定,哪些異常拋出時不觸發降級(不去調用fallbackMethod),而是將異常向上拋出。

  8:observableExecutionMode:定義hystrix observable command的模式;

  9:raiseHystrixExceptions:任何不可忽略的異常都包含在HystrixRuntimeException中;

  10:defaultFallback:默認的回調函數,該函數的函數體不能有入參,返回值類型與@HystrixCommand修飾的函數體的返回值一致。如果指定了fallbackMethod,則fallbackMethod優先級更高。

2.2 信號量隔離(SEMAPHORE)

 

        用於隔離本地代碼或可快速返回的遠程調用(如memcached,redis)可以直接使用信號量隔離,降低線程隔離的上下文切換開銷。

        線程隔離會帶來線程開銷,有些場景(比如無網絡請求場景)可能會因為用開銷換隔離得不償失,為此hystrix提供了信號量隔離。

        主要適用場景: 並發需求不大的依賴調用(因為如果並發需求較大,相應的信號量的數量就要設置得夠大,因為Tomcat線程與處理線程為同一個線程,那么這個依賴調用就會占用過多的Tomcat線程資源,有可能會影響到其他服務的接收)

        和線程池隔離類似,同一個HystrixCommandGroupKey共用一個信號量(默認為類名)

public class CommandUsingSemaphoreIsolation extends HystrixCommand<String> {
    private final int id;
    public CommandUsingSemaphoreIsolation(int id) {
        super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"))
                // since we're doing an in-memory cache lookup we choose SEMAPHORE isolation
                .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                        .withExecutionIsolationStrategy(ExecutionIsolationStrategy.SEMAPHORE)));
        this.id = id;
    }
    @Override
    protected String run() {
        // a real implementation would retrieve data from in memory data structure
        return "ValueFromHashMap_" + id;
   }
}

2.3 線程池隔離與信號量隔離區別

線程池隔離:
      1、調用線程和hystrixCommand線程不是同一個線程,並發請求數受到線程池(不是容器tomcat的線程池,而是hystrixCommand所屬於線程組的線程池)中的線程數限制,默認是10。
      2、這個是默認的隔離機制
      3、hystrixCommand線程無法獲取到調用線程中的ThreadLocal中的值
   信號量隔離:
      1、調用線程和hystrixCommand線程是同一個線程,默認最大並發請求數是10
      2、調用數度快,開銷小,由於和調用線程是處於同一個線程,所以必須確保調用的微服務可用性足夠高並且返回快才用

注意:如果發生找不到上下文的運行時異常,可考慮將隔離策略設置為SEMAPHONE。

官方圖示:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM