四、Hystrix的線程池+服務+接口劃分以及資源池的容量大小控制

4.1  隔離策略execution.isolation.strategy

 

指定了HystrixCommand.run()的資源隔離策略,THREAD或者SEMAPHORE,一種是基於線程池,一種是信號量

線程池機制,每個command運行在一個線程池中,限流是通過線程池的大小來控制的

信號量機制,command是運行在調用線程中,但是通過信號量的容量來進行限流

 

如何在線程池和信號量之間做選擇?

 

默認的策略就是線程池

線程池其實最大的好處就是對於網絡訪問請求,如果有超時的話,可以避免調用線程阻塞住

而使用信號量的場景,通常是針對超大併發量的場景下,每個服務實例每秒都幾百的QPS,那麼此時你用線程池的話,線程一般不會太多,可能撐不住那麼高的併發,如果要撐住,可能要耗費大量的線程資源,那麼就是用信號量,來進行限流保護

 

一般用信號量常見於那種基於純內存的一些業務邏輯服務,而不涉及到任何網絡訪問請求

netflix有100+的command運行在40+的線程池中,只有少數command是不運行在線程池中的,就是從純內存中獲取一些元數據,或者是對多個command包裝起來的facacde command,是用信號量限流的

 

// to use thread isolation

HystrixCommandProperties.Setter()

   .withExecutionIsolationStrategy(ExecutionIsolationStrategy.THREAD)

// to use semaphore isolation

HystrixCommandProperties.Setter()

   .withExecutionIsolationStrategy(ExecutionIsolationStrategy.SEMAPHORE)

 

4.2  Command名稱和Command組

線程池隔離,依賴服務->接口->線程池,如何來劃分

你的每個command,都可以設置一個自己的名稱,同時可以設置一個自己的組

private static final Setter cachedSetter =

    Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"))

        .andCommandKey(HystrixCommandKey.Factory.asKey("HelloWorld"));   

 

public CommandHelloWorld(String name) {

    super(cachedSetter);

    this.name = name;

}

 

command group,是一個非常重要的概念,默認情況下,因爲就是通過command group來定義一個線程池的,而且還會通過command group來聚合一些監控和報警信息

 

同一個command group中的請求,都會進入同一個線程池中

Setter

                    //CommondGroup:默認情況下,因爲就是通過command group來定義一個線程池的,統計信息,成功次數,[timeout(thread)]超時次數,失敗次數,可以看到某一個服務整體的一些訪問情況

                    .withGroupKey(HystrixCommandGroupKey.Factory.asKey("AssociatedExamAllCourses"))

                    //CommondKey:代表了一類command,一般來說代表了底層的依賴服務的一個接口,多個command key屬於一個command group,在做統計的時候,會放在一起統計

                    .andCommandKey(jointExamWholeAnalysis)

 

4.3  線程池threadpool key指定線程池名稱

threadpool key代表了一個HystrixThreadPool,用來進行統一監控,統計,緩存

 

默認的threadpool key就是command group名稱

每個command都會跟它的threadpool key對應的thread pool綁定在一起

如果不想直接用command group,也可以手動設置thread pool name

 

public CommandHelloWorld(String name) {

    super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"))

            .andCommandKey(HystrixCommandKey.Factory.asKey("HelloWorld"))

            .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("HelloWorldPool")));

    this.name = name;

}

//CommondThreadpool:對於thread pool資源隔離來說,可能是希望能夠拆分的更加一致一些,比如在一個功能模塊內,對不同的請求可以使用不同的thread pool

                    //同一個服務的不同接口,做一個細粒度的資源隔離,每個command key有自己的線程池,每個接口有自己的線程池,去做資源隔離和限流

                    .andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey("associatedExamAllCoursesThreadPool"))

 

command threadpool -> command group(服務) -> command key(接口)

 

command key,代表了一類command,一般來說,代表了底層的依賴服務的一個接口

command group,代表了某一個底層的依賴服務,合理,一個依賴服務可能會暴露出來多個接口,每個接口就是一個command key

command group,在邏輯上去組織起來一堆command key的調用,統計信息,成功次數,timeout超時次數,失敗次數,可以看到某一個服務整體的一些訪問情況

command group,一般來說,推薦是根據一個服務去劃分出一個線程池,command key默認都是屬於同一個線程池的

 

比如說你以一個服務爲粒度,估算出來這個服務每秒的所有接口加起來的整體QPS在100左右,你調用那個服務的當前服務,部署了10個服務實例,每個服務實例上,其實用這個command group對應這個服務,給一個線程池,量大概在10個左右,就可以了,你對整個服務的整體的訪問QPS大概在每秒100左右

 

一般來說,command group(Service)是用來在邏輯上組合一堆command的(Facade)

舉個例子,對於一個服務中的某個功能模塊來說,希望將這個功能模塊內的所有command放在一個group中,那麼在監控和報警的時候可以放一起看

 

但有一種情況,command group,對應了一個服務,但是這個服務暴露出來的幾個接口,訪問量很不一樣,差異非常之大,你可能就希望在這個服務command group內部,包含的對應多個接口的command key,做一些細粒度的資源隔離

對同一個服務的不同接口,都使用不同的線程池

command key -> command group

command key -> 自己的threadpool key

邏輯上來說,多個command key屬於一個command group,在做統計的時候,會放在一起統計。

每個command key(接口)有自己的線程池,每個接口有自己的線程池,去做資源隔離和限流。

但是對於thread pool資源隔離來說,可能是希望能夠拆分的更加一致一些,比如在一個功能模塊內,對不同的請求可以使用不同的thread pool

command group一般來說,可以是對應一個服務,多個command key對應這個服務的多個接口,多個接口的調用共享同一個線程池

如果說你的command key,要用自己的線程池,可以定義自己的threadpool key,就ok了

 

4.4  CoreSize線程池大小

設置線程池的大小,默認是10

HystrixThreadPoolProperties.Setter()

   .withCoreSize(int value)

一般來說,用這個默認的10個線程大小就夠了

HystrixThreadPoolProperties.Setter()

                            //CoreSize:設置線程池的大小,默認是10,如果你不設置另外兩個queue相關的參數,等待隊列是關閉

                            //先進去線程池的是10個請求,5個請求進入等待隊列,線程池裏有空閒,等待隊列中的請求如果還沒有timeout,那麼就進去線程池去執行

                            .withCoreSize(10)

                            //設置線程池的最大大小,只有在設置allowMaximumSizeToDivergeFromCoreSize的時候才能生效

 

4.5  QueueSizeRejectionThreshold閾值設置

 

控制queue滿後reject的threshold,因爲maxQueueSize不允許熱修改,因此提供這個參數可以熱修改,控制隊列的最大大小

HystrixCommand在提交到線程池之前,其實會先進入一個隊列中,這個隊列滿了之後,纔會reject。默認值是5

 

HystrixThreadPoolProperties.Setter()

   .withQueueSizeRejectionThreshold(int value)

//QueueSizeRejectionThreshold:控制隊列的最大大小HystrixCommand在提交到線程池之前,其實會先進入一個隊列中,這個隊列滿了之後,纔會reject

                            //如果withMaxQueueSize<withQueueSizeRejectionThreshold,那麼取的是withMaxQueueSize,反之,取得是withQueueSizeRejectionThreshold

                            .withQueueSizeRejectionThreshold(5)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章