1. 程式人生 > >Hystrix 使用手冊 | 官方文件翻譯

Hystrix 使用手冊 | 官方文件翻譯

由於時間關係可能還沒有翻譯全,但重要部分已基本包含

本人水平有限,如有翻譯不當,請多多批評指出,我一定會修正,謝謝大家。有關 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 [email protected]: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 exception
  • HystrixObservableCommand.construct() — returns an Observable that emits the response(s) or sends an onError notification

If the run() or construct() method exceeds the command’s timeout value, the thread will throw a TimeoutException (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 value run() or construct() 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 an Observable that emits the single response and then makes an onCompleted notification; in the case of construct() Hystrix returns the same Observable returned by construct().

時序圖

熔斷器

隔離機制

執行緒與執行緒池

請求合併

快取

 

如何使用

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 TypeException classException.causesubject 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

暫未