由於時間關系可能還沒有翻譯全,但重要部分已基本包含
本人水平有限,如有翻譯不當,請多多批評指出,我一定會修正,謝謝大家。有關 ObservableHystrixCommand 我有的部分選擇性忽略了,因為常用的是 HystrixCommand,但每一個例子都有這兩種 command 的解釋
最好的學習方式其實還是看官方原文,下面附上鏈接
官方文檔地址:https://github.com/Netflix/hystrix/wiki
簡述
什么是 Hystrix?
在分布式環境中,不可避免地會遇到所依賴的服務掛掉的情況,Hystrix 可以通過增加 延遲容忍度 與 錯誤容忍度,來控制這些分布式系統的交互。Hystrix 在服務與服務之間建立了一個中間層,防止服務之間出現故障,並提供了失敗時的 fallback 策略,來增加你系統的整體可靠性和彈性。
Hystrix 做了那些事情?
Hystrix 提供了以下服務
- 引入第三方的 client 類庫,通過延遲與失敗的檢測,來保護服務與服務之間的調用(網絡間調用最為典型)
- 阻止復雜的分布式系統中出現級聯故障
- 快速失敗與快速恢復機制
- 提供兜底方案(fallback)並在適當的時機優雅降級
- 提供實時監控、報警與操作控制
Hystrix 解決了什么問題?
在復雜的分布式架構中,服務之間都是相互依賴的,任何一個節點都不可避免會宕機。如果主節點不能從這些宕機節點中獨立出來,那主節點將會面臨被這些宕機的節點拖垮的風險。舉個例子,如果一個應用依賴了 30 個服務,每個服務保證 99.99% 的時間是正常的,那可以計算出
99.9930 = 99.7% uptime
0.3% of 1 billion requests = 3,000,000 failures
2+ hours downtime/month even if all dependencies have excellent uptime.
實際情況往往更糟糕
完好情況下,請求流如下:

當一個依賴的節點壞掉時,將阻塞整個的用戶請求:

流量高峰時,一個單節點的宕機或延遲,會迅速導致所有服務負載達到飽和。應用中任何一個可能通過網絡訪問其他服務的節點,都有可能成為造成潛在故障的來源。更嚴重的是,還可能導致服務之間的延遲增加,占用隊列、線程等系統資源,從而導致多系統之間的級聯故障。

更嚴重的是,當網絡請求是通過第三方的一個黑盒客戶端來發起時,實現細節都被隱藏起來了,而且還可能頻繁變動,這樣發生問題時就很難監控和改動。如果這個第三方還是通過傳遞依賴的,主應用程序中根本沒有顯示地寫出調用的代碼,那就更難了。
網絡連接失敗或者有延遲,服務將會產生故障或者響應變慢,最終反應成為一個 bug。
所有上述表現出來的故障或延遲,都需要一套管理機制,將節點變得相對獨立,這樣任何一個單節點故障,都至少不會拖垮整個系統的可用性。
Hystrix 的設計原則是什么?
Hystrix 通過以下設計原則來運作:
- 防止任何一個單節點將容器中的所有線程都占滿
- 通過快速失敗,取代放在隊列中等待
- 提供在故障時的應急方法(fallback)
- 使用隔離技術 (如 bulkhead, swimlane, 和 circuit breaker patterns) 來限制任何一個依賴項的影響面
- 提供實時監控、報警等手段
- 提供低延遲的配置變更
- 防止客戶端執行失敗,不僅僅是執行網絡請求的客戶端
Hystrix 如何時間它的目標?
如下:
- 將遠程請求或簡單的方法調用包裝成
HystrixCommand或者HystrixObservableCommand對象,啟動一個單獨的線程來運行。 - 你可以為服務調用定義一個超時時間,可以為默認值,或者你自定義設置該屬性,使得99.5%的請求時間都在該時間以下。
- 為每一個依賴的服務都分配一個線程池,當該線程池滿了之后,直接拒絕,這樣就防止某一個依賴的服務出問題阻塞了整個系統的其他服務
- 記錄成功數、失敗數、超時數以及拒絕數等指標
- 設置一個熔斷器,將所有請求在一段時間內打到這個熔斷器提供的方法上,觸發條件可以是手動的,也可以根據失敗率自動調整。
- 實時監控配置與屬性的變更
當你啟用 Hystrix 封裝了原有的遠程調用請求后,整個流程圖變為下圖所示。

接下來讓我們學習如何使用它吧
快速入門
獲取源碼
maven
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
<version>x.y.z</version>
</dependency>
lvy
<dependency org="com.netflix.hystrix" name="hystrix-core" rev="x.y.z" />
如果你想下載 Jar 包而不是構建在一個工程里,如下
<?xml version="1.0"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.netflix.hystrix.download</groupId> <artifactId>hystrix-download</artifactId> <version>1.0-SNAPSHOT</version> <name>Simple POM to download hystrix-core and dependencies</name> <url>http://github.com/Netflix/Hystrix</url> <dependencies> <dependency> <groupId>com.netflix.hystrix</groupId> <artifactId>hystrix-core</artifactId> <version>x.y.z</version> <scope/> </dependency> </dependencies> </project>
然后執行
mvn -f download-hystrix-pom.xml dependency:copy-dependencies
Hello World
最簡單的示例
public class CommandHelloWorld extends HystrixCommand<String> { private final String name; public CommandHelloWorld(String name) { super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup")); this.name = name; } @Override protected String run() { // a real example would do work like a network call here return "Hello " + name + "!"; } }
該 commond 類可以用以下方法使用
String s = new CommandHelloWorld("Bob").execute(); Future<String> s = new CommandHelloWorld("Bob").queue(); Observable<String> s = new CommandHelloWorld("Bob").observe();
更多具體的用法詳見 如何使用 模塊
構建
下載源碼並構建
$ git clone git@github.com:Netflix/Hystrix.git $ cd Hystrix/ $ ./gradlew build
或者像這樣構建
$ ./gradlew clean build
構建的輸出大概是這樣的
$ ./gradlew build :hystrix-core:compileJava :hystrix-core:processResources UP-TO-DATE :hystrix-core:classes :hystrix-core:jar :hystrix-core:sourcesJar :hystrix-core:signArchives SKIPPED :hystrix-core:assemble :hystrix-core:licenseMain UP-TO-DATE :hystrix-core:licenseTest UP-TO-DATE :hystrix-core:compileTestJava :hystrix-core:processTestResources UP-TO-DATE :hystrix-core:testClasses :hystrix-core:test :hystrix-core:check :hystrix-core:build :hystrix-examples:compileJava :hystrix-examples:processResources UP-TO-DATE :hystrix-examples:classes :hystrix-examples:jar :hystrix-examples:sourcesJar :hystrix-examples:signArchives SKIPPED :hystrix-examples:assemble :hystrix-examples:licenseMain UP-TO-DATE :hystrix-examples:licenseTest UP-TO-DATE :hystrix-examples:compileTestJava :hystrix-examples:processTestResources UP-TO-DATE :hystrix-examples:testClasses :hystrix-examples:test :hystrix-examples:check :hystrix-examples:build BUILD SUCCESSFUL Total time: 30.758 secs
clean build 方式的輸出如下
> Building > :hystrix-core:test > 147 tests completed
工作原理
流程圖
下圖展示了當你用使用 Hystrix 封裝后的客戶端請求一個服務時的流程

1. 創建 HystrixCommand 或 HystrixObservableCommand 對象
通過構建這兩個對象來發起請求,構造函數中可以傳入你發起請求時需要的參數
如果你需要的是返回一個單獨的響應,那你就用 HystrixCommand 對象
HystrixCommand command = new HystrixCommand(arg1, arg2);
入股你需要的是聚合起來的多個響應,就用 HystrixObservableCommand 對象
HystrixObservableCommand command = new HystrixObservableCommand(arg1, arg2);
2. 執行 command
一共有四種方式可以執行 command,其中前兩種方式都只適用於簡單的 HystrixCommand 對象
- excute() — 以阻塞方式運行,並返回返回其包裝對象的響應值,或者拋出異常
- queue() — 返回一個 Future 對象,你可以選擇在適當時機 get
- observe() —
- toObservable() —
K value = command.execute(); Future<K> fValue = command.queue(); Observable<K> ohValue = command.observe(); //hot observable Observable<K> ocValue = command.toObservable(); //cold observable
實際上,同步方法 execute() 底層邏輯是調用 queue().get(),然后 queue() 實際上是調用了 toObservable().toBlocking().toFuture(),也就是說所有 HystrixCommand 的邏輯都是走 Observable 實現
3. 是否請求緩存
如果開啟了請求緩存,並且該響應可以在緩存中找到,那就立刻返回緩存的響應值,而不會再走遠程調用邏輯
4. 是否開啟熔斷
當執行 command 時,Hystrix 會判斷熔斷是否開啟,如果是開啟狀態則走 (8) 進行 Fallback 降級策略,如果未開啟則走 (5) ,繼續下一步判斷是否可以執行 command
5. 線程池\隊列\信號量 是否已滿
如果上述三者已達到閾值,Hystrix 就會直接走 (8) 進行 Fallback 降級策略
6. HystrixObservableCommand.construct() 或 HystrixCommand.run()
這段太難了,不太會翻譯,日后有理解再補充
Here, Hystrix invokes the request to the dependency by means of the method you have written for this purpose, one of the following:
HystrixCommand.run()— returns a single response or throws an exceptionHystrixObservableCommand.construct()— returns an Observable that emits the response(s) or sends anonErrornotificationIf the
run()orconstruct()method exceeds the command’s timeout value, the thread will throw aTimeoutException(or a separate timer thread will, if the command itself is not running in its own thread). In that case Hystrix routes the response through 8. Get the Fallback, and it discards the eventual return valuerun()orconstruct()method if that method does not cancel/interrupt.Please note that there's no way to force the latent thread to stop work - the best Hystrix can do on the JVM is to throw it an InterruptedException. If the work wrapped by Hystrix does not respect InterruptedExceptions, the thread in the Hystrix thread pool will continue its work, though the client already received a TimeoutException. This behavior can saturate the Hystrix thread pool, though the load is 'correctly shed'. Most Java HTTP client libraries do not interpret InterruptedExceptions. So make sure to correctly configure connection and read/write timeouts on the HTTP clients.
If the command did not throw any exceptions and it returned a response, Hystrix returns this response after it performs some some logging and metrics reporting. In the case of
run(), Hystrix returns anObservablethat emits the single response and then makes anonCompletednotification; in the case ofconstruct()Hystrix returns the sameObservablereturned byconstruct().
時序圖
熔斷器
隔離機制
線程與線程池
請求合並
緩存
如何使用
Hello World
HystrixCommand 實現
public class CommandHelloWorld extends HystrixCommand<String> { private final String name; public CommandHelloWorld(String name) { super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup")); this.name = name; } @Override protected String run() { // a real example would do work like a network call here return "Hello " + name + "!"; } }
HystrixObservableCommand 實現
public class CommandHelloWorld extends HystrixObservableCommand<String> { private final String name; public CommandHelloWorld(String name) { super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup")); this.name = name; } @Override protected Observable<String> construct() { return Observable.create(new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> observer) { try { if (!observer.isUnsubscribed()) { // a real example would do work like a network call here observer.onNext("Hello"); observer.onNext(name + "!"); observer.onCompleted(); } } catch (Exception e) { observer.onError(e); } } } ).subscribeOn(Schedulers.io()); } }
同步執行
調用 execute 方法即可
String s = new CommandHelloWorld("World").execute();
測試用例如下
@Test public void testSynchronous() { assertEquals("Hello World!", new CommandHelloWorld("World").execute()); assertEquals("Hello Bob!", new CommandHelloWorld("Bob").execute()); }
對於 HystrixObservableCommand 可以用 .toBlocking().toFuture().get()
異步執行
調用 queue 方法即可
Future<String> fs = new CommandHelloWorld("World").queue();
返回值可以這樣拿到
String s = fs.get();
測試用例如下
@Test public void testAsynchronous1() throws Exception { assertEquals("Hello World!", new CommandHelloWorld("World").queue().get()); assertEquals("Hello Bob!", new CommandHelloWorld("Bob").queue().get()); } @Test public void testAsynchronous2() throws Exception { Future<String> fWorld = new CommandHelloWorld("World").queue(); Future<String> fBob = new CommandHelloWorld("Bob").queue(); assertEquals("Hello World!", fWorld.get()); assertEquals("Hello Bob!", fBob.get()); }
以下兩種寫法是等價的
String s1 = new CommandHelloWorld("World").execute(); String s2 = new CommandHelloWorld("World").queue().get();
對於 HystrixObservableCommand 可以用 .toBlocking().toFuture()
Reactive Execution
暫未翻譯
Reactive Commands
暫未翻譯
Fallback
你可以為 Hystrix 提供一個降級策略並提供相應的降級方法 Fallback,這樣當調用出錯時,Hystrix 會選擇執行你的 Fallback 方法並返回。你可以為大多數的 command 都設置降級策略,但以下幾種情況除外:
- 寫操作:如果一個方法只是寫操作,而不需要返回一個值,其實就是返回值為 void 的方法。這時候你就不需要再設置 fallback 了。如果寫失敗了你反而希望錯誤信息傳遞過來
- 離線計算:如果一個方法的使命是寫緩存、生成報告、或者大量的離線計算,這時最好不要設置 fallback,讓錯誤信息返回以便重試,而不是毫無察覺地替換為降級方法
啟用 fallback 你只需要實現 HystrixCommand 的 fallback() 方法即可,Hystrix 將會在錯誤發生時執行該方法,所謂的錯誤包括:拋出異常、超時、線程池或信號量觸發拒絕、熔斷器打開。
public class CommandHelloFailure extends HystrixCommand<String> { private final String name; public CommandHelloFailure(String name) { super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup")); this.name = name; } @Override protected String run() { throw new RuntimeException("this command always fails"); } @Override protected String getFallback() { return "Hello Failure " + name + "!"; } }
該 run 方法每次都必然拋出異常,然后執行降級方法,以下為測試用例
@Test public void testSynchronous() { assertEquals("Hello Failure World!", new CommandHelloFailure("World").execute()); assertEquals("Hello Failure Bob!", new CommandHelloFailure("Bob").execute()); }
Error Propagation
run() 方法拋出的所有異常,除了 HystrixBadRequestException 以外,都會記為失敗數,並觸發 fallback 和熔斷器的相關邏輯。
| Failure Type | Exception class | Exception.cause | subject to fallback |
|---|---|---|---|
| FAILURE | HystrixRuntimeException |
underlying exception (user-controlled) | YES |
| TIMEOUT | HystrixRuntimeException |
j.u.c.TimeoutException |
YES |
| SHORT_CIRCUITED | HystrixRuntimeException |
j.l.RuntimeException |
YES |
| THREAD_POOL_REJECTED | HystrixRuntimeException |
j.u.c.RejectedExecutionException |
YES |
| SEMAPHORE_REJECTED | HystrixRuntimeException |
j.l.RuntimeException |
YES |
| BAD_REQUEST | HystrixBadRequestException |
underlying exception (user-controlled) |
Command Name
一個 command 的名字,默認根據類名來定義
getClass().getSimpleName();
明確定義 command 的名稱,需要通過構造方法傳入
public CommandHelloWorld(String name) { super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup")) .andCommandKey(HystrixCommandKey.Factory.asKey("HelloWorld"))); this.name = name; }
你也可以把固定的 Setter 保存起來,以便每次都傳入一樣的值
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
Hystrix 用這個分組的 key 去做統一的報表、監控、儀表盤等數據統計。上面代碼中已經包含
Command Thread-Pool
thread-pool key 對應着 HystrixThreadPool,每一個 command 都屬於一個 HystrixTreadPool,也即對應着一個 HystrixThreadPoolKey。如果不指定,那就默認同 HystrixGroupKey 相同。
之所欲需要這個參數,而不是用不同的 Group Key 來區分,是因為有時候你需要用 Group Key 來做數據的統計,但同時又希望里面的 command 進行分組獨立。
以下為一個例子
- 兩個 command 用於獲取一個視頻的元信息
- group 名為 “VideoMetadata”
- command A 依賴資源 a
- command B 依賴資源 b
這種情況下,如果 command A 有問題比如說延遲之類的,對它的處理不應該影響到 command B,因為他們請求的是不同的后台資源。所以,我們希望這兩個 command 邏輯上成為一個整體,但隔離時又希望他們是獨立的,就需要設置這個參數。
Request Cache
請求緩存可以通過實現 getRequestKey 方法
public class CommandUsingRequestCache extends HystrixCommand<Boolean> { private final int value; protected CommandUsingRequestCache(int value) { super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup")); this.value = value; } @Override protected Boolean run() { return value == 0 || value % 2 == 0; } @Override protected String getCacheKey() { return String.valueOf(value); } }
由於這個依賴請求的上下文,所以我們必須先初始化 HystrixRequestContext,測試代碼如下
@Test public void testWithoutCacheHits() { HystrixRequestContext context = HystrixRequestContext.initializeContext(); try { assertTrue(new CommandUsingRequestCache(2).execute()); assertFalse(new CommandUsingRequestCache(1).execute()); assertTrue(new CommandUsingRequestCache(0).execute()); assertTrue(new CommandUsingRequestCache(58672).execute()); } finally { context.shutdown(); } }
一般來說這個 context 對象的初始化和銷毀應該通過 ServletFilter 來控制。下面的例子展示了 context 對象對緩存的影響(包括獲取的值以及是否是從緩存中獲取的這個判斷)
@Test public void testWithCacheHits() { HystrixRequestContext context = HystrixRequestContext.initializeContext(); try { CommandUsingRequestCache command2a = new CommandUsingRequestCache(2); CommandUsingRequestCache command2b = new CommandUsingRequestCache(2); assertTrue(command2a.execute()); // this is the first time we've executed this command with // the value of "2" so it should not be from cache assertFalse(command2a.isResponseFromCache()); assertTrue(command2b.execute()); // this is the second time we've executed this command with // the same value so it should return from cache assertTrue(command2b.isResponseFromCache()); } finally { context.shutdown(); } // start a new request context context = HystrixRequestContext.initializeContext(); try { CommandUsingRequestCache command3b = new CommandUsingRequestCache(2); assertTrue(command3b.execute()); // this is a new request context so this // should not come from cache assertFalse(command3b.isResponseFromCache()); } finally { context.shutdown(); } }
Request Collapsing
這個技術允許多個請求被壓縮在一個單獨的 command 里面發出請求。
Operations
配置
Command Properties
Execution:決定了 command 如何被 execute
- execution.isolation.strategy:以哪種隔離策略執行,分為 THREAD 和 SEMAPHORE 兩種。默認的同時也是推薦的方式是,HystrixCommand 用 THREAD 方式,HystrixObservableCommand 用 SEMAPHORE 方式。如果不是 QPS 特別特別高,一般是非遠程調用,沒必要用 SEMAPHORE 來控制,用 THREAD 就好了。
- execution.isolation.thread.timeoutInMilliseconds:HystrixCommand 默認是有超時時間控制(execution.timeout.enabled = true)並且分配降級策略的,這個參數就設定了超時時間,默認為 1000 ms
- execution.timeout.enabled:如上所述,是否開啟超時控制,默認為 true
- execution.isolation.thread.interruptOnTimeout:超時后是否允許 interrupt,默認為 true
- execution.isolation.thread.interruptOnCancel:cancel 后是否 interrupt,默認為 false
- execution.isolation.semaphore.maxConcurrentRequests:如果你的隔離策略配置的是 ExecutionIsolationStrategy.SEMAPHORE,那這個參數就是表明信號量的值,也就是最大的並發請求數。如果達到了這個值,隨后的請求將會被拒絕。默認為 10。你設置這個信號量值的邏輯,應該和你選擇網線程池里放多少個線程的邏輯是一樣的,但信號量的開銷要小得多,而且方法的執行速度也要快得多,如果不是這樣的情況,最好還是選擇線程池方式,也就是 THREAD
Fallback:以下配置決定了 HystrixCommand.getFallback 的邏輯,這些配置同時適用於 THREAD 和 SEMAPHORE
- fallback.isolation.semaphore.maxConcurrentRequests:該值為請求 Fallback 的最大並發請求數,默認為 10,如果達到了這個值,隨后的請求將會拋出異常
- fallback.enabled:當錯誤或超時發生時,是否走降級策略,默認為 true
Circuit Breaker
- circuitBreaker.enabled:是否開啟熔斷器,默認為 true
- circuitBreaker.requestVolumeThreshold:滑動窗口大小,即觸發熔斷的最小請求數量,默認為 20。舉個例子,一共只有 19 個請求落在窗口內,就算全都失敗了,也不會觸發熔斷
- circuitBreaker.sleepWindowInMilliseconds:設置一個時間,當觸發熔斷后,多少秒之后再次進行訪問嘗試,看是否仍然要保持熔斷狀態,默認為 5000ms
- circuitBreaker.errorThresholdPercentage:設置一個失敗率,失敗的請求達到這個值時,就觸發熔斷,默認為 50%
- circuitBreaker.forceOpen:這個值沒太看懂什么意思,附上原文(This property, if
true, forces the circuit breaker into an open (tripped) state in which it will reject all requests.) - circuitBreaker.forceClosed:這個值沒太看懂什么意思,附上原文(This property, if true, forces the circuit breaker into a closed state in which it will allow requests regardless of the error percentage.The circuitBreaker.forceOpen property takes precedence so if it is set to true this property does nothing.)
Metrics:該配置指定了如何在運行過程中收集 metrics
- metrics.rollingStats.timeInMilliseconds:指標收集的滑動窗口時間,也就是 Hystrix 保持多久的一個指標收集,為之后的使用和上報做准備,默認為 10000 ms。下圖為具體圖示
- metrics.rollingStats.numBuckets:配合上面的參數使用,表示一個滑動窗口時間被分割為多少個 buckets 來進行細粒度指標收集,默認為 10
- metrics.rollingPercentile.enabled:進行百分比、均值等指標的收集,默認為 true,如果不選,則所有這類的指標返回 -1
- metrics.rollingPercentile.timeInMilliseconds:進行百分比均值等指標收集的窗口時間,默認為 60000 ms
- metrics.rollingPercentile.numBuckets:同理,上述百分比指標將被分為多少個 buckets 來進行收集,必須整除
- metrics.rollingPercentile.bucketSize:收集百分比指標時,每一個 buckets 最大收集的請求數,默認為 100。舉個例子,如果該值設置為 100,那一個 bucket 有 500 個請求過來時,只會用后 100 個請求做指標計算。
- metrics.healthSnapshot.intervalInMilliseconds:設置一個時間,來指定收集健康指標的時間間隔(比如計算成功數、錯誤率等),默認為 500ms。該指標的意義是如果你的系統 CPU 負載很高,該指標計算同樣也是 CPU 密集型運算,這個值可以讓你控制多久進行一次健康統計
Request Context:以下參數會影響 HystrixRequestContex
- requestCache.enabled:該參數決定了 HystrixCommand.getCacheKey 是否被啟用,默認為 true
- requestLog.enabled:該參數決定了執行過程中的日志,是否會輸出到 HystrixRequestLog
Collapser Properties
不重要,過
Thread Pool Properties
以下參數控制 command 在執行時所需的線程池參數,與 Java 中的 ThreadPoolExecutor 的參數是對應的。大多數情況下 10 個線程足夠了(甚至更小)。要想判斷到底多少個線程合適,有以下的經驗計算公式
流量頂峰時的 QPS * 99%請求時延 + 一些用來緩沖的空間

- coreSize:核心線程數,默認為 10
- maximumSize:最大線程數,該參數在
allowMaximumSizeToDivergeFromCoreSize為 true 時才生效,默認與核心線程數一樣,都是 10 - maxQueueSize:設置 BlockingQueue 所實現隊列的最大隊列大小,默認為 -1。為 -1 代表用的是 SynchronousQueue,否則就是固定大小的 LinkedBlockingQueue。當核心線程池的線程都在忙碌時,新請求將會落在這個隊列里,但超出隊列部分將會被拒絕
- allowMaximumSizeToDivergeFromCoreSize:是否允許線程池的大小擴大到 maximumSize,默認為 false
- queueSizeRejectionThreshold:當隊列里的等待線程數達到該值時,隨后的請求將會被拒絕,即使還沒達到 maxQueueSize。該參數的意義是因為 maxQueueSize 在線程剛創建時就固定了大小,無法改變,該值可以彌補這個缺憾,所以有時候 maxQueueSize 不起作用就是因為這個。默認為 5
- keepAliveTimeMinutes:1.5.9版本之前,線程池是固定大小的(相當於 coreSize == maximumSize),而之后的版本這兩個值可能不同,線程池可能會創建或銷毀線程以動態調整。該參數指定了線程多久不使用就被釋放掉,默認值是 1min
- metrics.rollingStats.timeInMilliseconds:監控線程池指標的滑動窗口時間,默認 10000 ms
- metrics.rollingStats.numBuckets:監控線程池指標的 buckets 數量,默認為 10,必須能被上一個指標整除
Metrics
暫未翻譯
Plugins
暫未翻譯
