咱們的配置都是基於 HystrixCommand 的,咱們經過在方法上添加 @HystrixCommand
註解並配置註解的參數來實現配置,但有的時候一個類裏面會有多個 Hystrix 方法,每一個方法都是相似配置的話會冗餘不少代碼,這時候咱們能夠在類上使用 @DefaultProperties
註解來給整個類的 Hystrix 方法設置一個默認值。java
下面是 HystrixCommand 支持的參數,除了 commandKey/observableExecutionMode/fallbackMethod
外,均可以使用 @DefaultProperties
配置默認值。spring
commandKey:用來標識一個 Hystrix 命令,默認會取被註解的方法名。須要注意:Hystrix 裏同一個鍵的惟一標識並不包括 groupKey
,建議取一個獨一二無的名字,防止多個方法之間由於鍵重複而互相影響。數組
groupKey:一組 Hystrix 命令的集合, 用來統計、報告,默認取類名,可不配置。緩存
threadPoolKey:用來標識一個線程池,若是沒設置的話會取 groupKey
,不少狀況下都是同一個類內的方法在共用同一個線程池,若是兩個共用同一線程池的方法上配置了一樣的屬性,在第一個方法被執行後線程池的屬性就固定了,因此屬性會以第一個被執行的方法上的配置爲準。併發
commandProperties:與此命令相關的屬性。異步
threadPoolProperties:與線程池相關的屬性,ui
observableExecutionMode:當 Hystrix 命令被包裝成 RxJava 的 Observer 異步執行時,此配置指定了 Observable 被執行的模式,默認是 ObservableExecutionMode.EAGER
,Observable 會在被建立後馬上執行,而 ObservableExecutionMode.EAGER
模式下,則會產生一個 Observable 被 subscribe 後執行。咱們常見的命令都是同步執行的,此配置項能夠不配置。this
ignoreExceptions:默認 Hystrix 在執行方法時捕獲到異常時執行回退,並統計失敗率以修改熔斷器的狀態,而被忽略的異常則會直接拋到外層,不會執行回退方法,也不會影響熔斷器的狀態。spa
raiseHystrixExceptions:當配置項包括 HystrixRuntimeException
時,全部的未被忽略的異常都會被包裝成 HystrixRuntimeException,配置其餘種類的異常好像並無什麼影響。.net
fallbackMethod:方法執行時熔斷、錯誤、超時時會執行的回退方法,須要保持此方法與 Hystrix 方法的簽名和返回值一致。
defaultFallback:默認回退方法,當配置 fallbackMethod 項時此項沒有意義,另外,默認回退方法不能有參數,返回值要與 Hystrix方法的返回值相同。
Hystrix 的命令屬性是由 @HystrixProperty
註解數組構成的,HystrixProperty 由 name 和 value 兩個屬性,數據類型都是字符串。
如下將全部的命令屬性分組來介紹。
execution.isolation.strategy: 配置請求隔離的方式,有 threadPool(線程池,默認)和 semaphore(信號量)兩種,信號量方式高效但配置不靈活,咱們通常採用 Java 裏經常使用的線程池方式。
execution.timeout.enabled:是否給方法執行設置超時,默認爲 true。
execution.isolation.thread.timeoutInMilliseconds:方法執行超時時間,默認值是 1000,即 1秒,此值根據業務場景配置。
execution.isolation.thread.interruptOnTimeout: execution.isolation.thread.interruptOnCancel:是否在方法執行超時/被取消時中斷方法。須要注意在 JVM 中咱們沒法強制中斷一個線程,若是 Hystrix 方法裏沒有處理中斷信號的邏輯,那麼中斷會被忽略。
execution.isolation.semaphore.maxConcurrentRequests:默認值是 10,此配置項要在 execution.isolation.strategy
配置爲 semaphore
時纔會生效,它指定了一個 Hystrix 方法使用信號量隔離時的最大併發數,超過此併發數的請求會被拒絕。信號量隔離的配置就這麼一個,也是前文說信號量隔離配置不靈活的緣由。
滑動窗口
: Hystrix 的統計器是由滑動窗口來實現的,咱們能夠這麼來理解滑動窗口:一位乘客坐在正在行駛的列車的靠窗座位上,列車行駛的公路兩側種着一排挺拔的白楊樹,隨着列車的前進,路邊的白楊樹迅速從窗口滑過,咱們用每棵樹來表明一個請求,用列車的行駛表明時間的流逝,那麼,列車上的這個窗口就是一個典型的滑動窗口,這個乘客能經過窗口看到的白楊樹就是 Hystrix 要統計的數據。
桶
: bucket 是 Hystrix 統計滑動窗口數據時的最小單位。一樣類比列車窗口,在列車速度很是快時,若是每掠過一棵樹就統計一次窗口內樹的數據,顯然開銷很是大,若是乘客將窗口分紅十分,列車前進行時每掠過窗口的十分之一就統計一次數據,開銷就徹底能夠接受了。 Hystrix 的 bucket (桶)也就是窗口 N分之一 的概念。
metrics.rollingStats.timeInMilliseconds:此配置項指定了窗口的大小,單位是 ms,默認值是 1000,即一個滑動窗口默認統計的是 1s 內的請求數據。
metrics.healthSnapshot.intervalInMilliseconds:它指定了健康數據統計器(影響 Hystrix 熔斷)中每一個桶的大小,默認是 500ms,在進行統計時,Hystrix 經過 metrics.rollingStats.timeInMilliseconds / metrics.healthSnapshot.intervalInMilliseconds
計算出桶數,在窗口滑動時,每滑過一個桶的時間間隔時就統計一次當前窗口內請求的失敗率。
metrics.rollingStats.numBuckets:Hystrix 會將命令執行的結果類型都統計彙總到一塊,給上層應用使用或生成統計圖表,此配置項即指定了,生成統計數據流時滑動窗口應該拆分的桶數。此配置項最易跟上面的 metrics.healthSnapshot.intervalInMilliseconds
搞混,認爲此項影響健康數據流的桶數。 此項默認是 10,而且須要保持此值能被 metrics.rollingStats.timeInMilliseconds
整除。
metrics.rollingPercentile.enabled:是否統計方法響應時間百分比,默認爲 true 時,Hystrix 會統計方法執行的 1%,10%,50%,90%,99%
等比例請求的平均耗時用以生成統計圖表。
metrics.rollingPercentile.timeInMilliseconds:統計響應時間百分比時的窗口大小,默認爲 60000,即一分鐘。
metrics.rollingPercentile.numBuckets:統計響應時間百分比時滑動窗口要劃分的桶用,默認爲6,須要保持能被metrics.rollingPercentile.timeInMilliseconds
整除。
metrics.rollingPercentile.bucketSize:統計響應時間百分比時,每一個滑動窗口的桶內要保留的請求數,桶內的請求超出這個值後,會覆蓋最前面保存的數據。默認值爲 100,在統計響應百分比配置全爲默認的狀況下,每一個桶的時間長度爲 10s = 60000ms / 6,但這 10s 內只保留最近的 100 條請求的數據。
circuitBreaker.enabled:是否啓用熔斷器,默認爲 true;
circuitBreaker.forceOpen: circuitBreaker.forceClosed:是否強制啓用/關閉熔斷器,強制啓用關閉都想不到什麼應用的場景,保持默認值,不配置便可。
circuitBreaker.requestVolumeThreshold:啓用熔斷器功能窗口時間內的最小請求數。試想若是沒有這麼一個限制,咱們配置了 50% 的請求失敗會打開熔斷器,窗口時間內只有 3 條請求,恰巧兩條都失敗了,那麼熔斷器就被打開了,5s 內的請求都被快速失敗。此配置項的值須要根據接口的 QPS 進行計算,值過小會有誤打開熔斷器的可能,值太大超出了時間窗口內的總請求數,則熔斷永遠也不會被觸發。建議設置爲 QPS * 窗口秒數 * 60%
。
circuitBreaker.errorThresholdPercentage:在經過滑動窗口獲取到當前時間段內 Hystrix 方法執行的失敗率後,就須要根據此配置來判斷是否要將熔斷器打開了。 此配置項默認值是 50,即窗口時間內超過 50% 的請求失敗後會打開熔斷器將後續請求快速失敗。
circuitBreaker.sleepWindowInMilliseconds:熔斷器打開後,全部的請求都會快速失敗,但什麼時候服務恢復正常就是下一個要面對的問題。熔斷器打開時,Hystrix 會在通過一段時間後就放行一條請求,若是這條請求執行成功了,說明此時服務極可能已經恢復了正常,那麼會將熔斷器關閉,若是此請求執行失敗,則認爲服務依然不可用,熔斷器繼續保持打開狀態。此配置項指定了熔斷器打開後通過多長時間容許一次請求嘗試執行,默認值是 5000。
requestCache.enabled:是否啓用請求結果緩存。默認是 true,但它並不意味着咱們的每一個請求都會被緩存。緩存請求結果和從緩存中獲取結果都須要咱們配置 cacheKey
,而且在方法上使用 @CacheResult
註解聲明一個緩存上下文。
requestLog.enabled:是否啓用請求日誌,默認爲 true。
fallback.enabled:是否啓用方法回退,默認爲 true 便可。
fallback.isolation.semaphore.maxConcurrentRequests:回退方法執行時的最大併發數,默認是10,若是大量請求的回退方法被執行時,超出此併發數的請求會拋出 REJECTED_SEMAPHORE_FALLBACK
異常。
線程池的配置也是由 HystrixProperty 數組構成,配置方式與命令屬性一致。
coreSize:核心線程池的大小,默認值是 10,通常根據 QPS * 99% cost + redundancy count
計算得出。
allowMaximumSizeToDivergeFromCoreSize:是否容許線程池擴展到最大線程池數量,默認爲 false;
maximumSize:線程池中線程的最大數量,默認值是 10,此配置項單獨配置時並不會生效,須要啓用 allowMaximumSizeToDivergeFromCoreSize
項。
maxQueueSize:做業隊列的最大值,默認值爲 -1,設置爲此值時,隊列會使用 SynchronousQueue
,此時其 size 爲0,Hystrix 不會向隊列內存放做業。若是此值設置爲一個正的 int 型,隊列會使用一個固定 size 的 LinkedBlockingQueue
,此時在覈心線程池內的線程都在忙碌時,會將做業暫時存放在此隊列內,但超出此隊列的請求依然會被拒絕。
queueSizeRejectionThreshold:因爲 maxQueueSize
值在線程池被建立後就固定了大小,若是須要動態修改隊列長度的話能夠設置此值,即便隊列未滿,隊列內做業達到此值時一樣會拒絕請求。此值默認是 5,因此有時候只設置了 maxQueueSize
也不會起做用。
keepAliveTimeMinutes:由上面的 maximumSize
,咱們知道,線程池內核心線程數目都在忙碌,再有新的請求到達時,線程池容量能夠被擴充爲到最大數量,等到線程池空閒後,多於核心數量的線程還會被回收,此值指定了線程被回收前的存活時間,默認爲 2,即兩分鐘。
Hystrix 內線程池的使用是基於 Java 內置線程池的簡單包裝,一般有如下三種狀態:
若是請求量少,達不到 coreSize,一般會使用核心線程來執行任務。
若是設置了 maxQueueSize
,當請求數超過了 coreSize, 一般會把請求放到 queue 裏,待覈心線程有空閒時消費。
若是 queue 長度沒法存儲請求,則會建立新線程執行直到達到 maximumSize
最大線程數,多出核心線程數的線程會在空閒時回收。
package com.ley.springcloud.hystrix.utils; import com.netflix.hystrix.HystrixCommand; /** * HystrixCommand配置常量Key * * @see com.netflix.hystrix.HystrixCommandProperties * @see com.netflix.hystrix.HystrixThreadPoolProperties * @see com.netflix.hystrix.HystrixCollapserProperties **/ public final class HystrixCommandConfigConstants { //Command properties is use to control HystrixCommand /** * <b>execution 配置控制HystrixCommand.run的執行</b> * * @see HystrixCommand#run() * @see com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand#commandProperties() * @see com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty **/ public static class ExecutionIsolationConstants { /** * 配置HystrixCommand.run的執行策略: THREAD|SEMAPHORE **/ public static final String EXECUTION_ISOLATION_STRATEGY = "execution.isolation.strategy"; /** * 配置HystrixCommand執行超時時間: 默認1000ms **/ public static final String EXECUTION_ISOLATION_THREAD_TIMEOUT_IN_MILLISECONDS = "execution.isolation.thread.timeoutInMilliseconds"; /** * 配置HystrixCommand.run執行是否啓用超時時間: 默認爲true **/ public static final String EXECUTION_TIMEOUT_ENABLED = "execution.timeout.enabled"; /** * 配置HystrixCommand.run()執行被取消的時候是否將它中斷: 默認爲true **/ public static final String EXECUTION_ISOLATION_THREAD_INTERRUPT_ON_TIMEOUT = "execution.isolation.thread.interruptOnTimeout"; /** * 當HystrixCommand的隔離策略使用信號量的時候,該屬性用來配置信號量的大小(併發請求數),<br/> * 當最大併發請求數達到該設置值,後續的請求將被拒絕: 默認10 **/ public static final String EXECUTION_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQUESTS = "execution.isolation.semaphore.maxConcurrentRequests"; } /** * fallback 控制HystrixCommand.getFallback()執行對於線程池或者信號量執行策略都生效 * * @see HystrixCommand#getFallback() * @see com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand#commandProperties() * @see com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty **/ public static class FallbackConstants { /** * 配置從調用線程中容許HystrixCommand.getFallback()方法的最大執行請求數<br/> * 當達到最大併發請求數時,後續請求將被拒絕並拋出異常: 默認10 **/ public static final String FALLBACK_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQUESTS = "fallback.isolation.semaphore.maxConcurrentRequests"; /** * 配置服務降級策略是否啓用: 默認true **/ public static final String FALLBACK_ENABLED = "fallback.enabled"; } /** * circuitBreaker配置 斷路器用來控制HystrixCircuitBreaker * * @see com.netflix.hystrix.HystrixCircuitBreaker * @see com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand#commandProperties() * @see com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty **/ public static class CircuitBreakerConstants { /** * 配置當服務請求命令失敗時,是否使用斷路器來跟蹤其健康指標和熔斷請求: 默認true **/ public static final String CIRCUIT_BREAKER_ENABLED = "circuitBreaker.enabled"; /** * 配置在滾動時間窗中,斷路器的最小請求數: 默認20 **/ public static final String CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD = "circuitBreaker.requestVolumeThreshold"; /** * 配置當斷路器打開以後的休眠時間窗,休眠時間窗結束以後,會將斷路器設置爲"半開",<br/> * 嘗試熔斷的請求命令,若是依然失敗就將斷路器繼續設置爲"打開"狀態,若是成功,就設置"關閉"<br/> * 默認5000ms **/ public static final String CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS = "circuitBreaker.sleepWindowInMilliseconds"; /** * 配置斷路器打開的錯誤百分比條件: 默認50%<br/> * 當在滾動時間窗中,若是請求數量超過circuitBreaker.errorThresholdPercentage前提下<br/> * 若是錯誤請求數的百分比超過50%,就把斷路器設置爲"打開"狀態 **/ public static final String CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE = "circuitBreaker.errorThresholdPercentage"; /** * 若是該屬性爲true,斷路器強制進入"打開"狀態,拒絕全部請求,優於circuitBreaker.forceClosed.<br/> * 默認爲false **/ public static final String CIRCUIT_BREAKER_FORCE_OPEN = "circuitBreaker.forceOpen"; /** * 若是該值設置爲true,斷路器強制進入"關閉"狀態,它會接受全部請求,默認爲true<br/> * 當配置了circuitBreaker.forceOpen,該屬性配置無效 **/ public static final String CIRCUIT_BREAKER_FORCE_CLOSED = "circuitBreaker.forceClosed"; } /** * metrics配置 主要度量HystrixCommand 和 HystrixObservableCommand 的執行指標信息 * * @see HystrixCommand#run() * @see com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand#commandProperties() * @see com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty **/ public static class MetricsConstants { /** * 配置滾動時間窗的長度,單位毫秒: 默認 10000ms(10s).<br/> * 該時間用於斷路器判斷健康度時須要手機信息的持續時間.<br/> * 斷路器在收集指標時會根據設置的時間窗拆分爲多個"桶"來累計各度量值,<br/> * 每一個"桶"記錄了一段時間內的採集指標.<br/> * 該屬性從Hystrix 1.4.12版本開始,只有在應用初始化的時候生效,<br/> * 經過動態刷新配置不會產生效果.避免出現運行期監測數據丟失的狀況 **/ public static final String METRICS_ROLLING_STATS_TIME_IN_MILLISECONDS = "metrics.rollingStats.timeInMilliseconds"; /** * 配置滾動時間窗統計信息時劃分"桶"的數量: 默認10<br/> * metrics.rollingStats.timeInMilliseconds參數設置必須能被該參數整除,不然拋出異常.<br/> * 該屬性從Hystrix 1.4.12版本開始,只有在應用初始化的時候生效,<br/> * 經過動態刷新配置不會產生效果.避免出現運行期監測數據丟失的狀況. **/ public static final String METRICS_ROLLING_STATS_NUM_BUCKETS = "metrics.rollingStats.numBuckets"; /** * 配置對命令執行是否使用百分位數來跟蹤和計算: 默認true<br/> * 若是配置<b>false</b>,全部概要統計均返回-1 **/ public static final String METRICS_ROLLING_PERCENTILE_ENABLED = "metrics.rollingPercentile.enabled"; /** * 配置百分位統計的滾動窗口的持續時間: 默認:60000ms(60s)<br/> * 該屬性從Hystrix 1.4.12版本開始,只有在應用初始化的時候生效,<br/> * 經過動態刷新配置不會產生效果.避免出現運行期監測數據丟失的狀況. **/ public static final String METRICS_ROLLING_PERCENTILE_TIME_IN_MILLISECONDS = "metrics.rollingPercentile.timeInMilliseconds"; /** * 配置百分位統計滾動窗口中使用"桶"的數量: 默認6<br/> * metrics.rollingPercentile.timeInMilliseconds必須能被該參數整除,不然拋出異常<br/> * 該屬性從Hystrix 1.4.12版本開始,只有在應用初始化的時候生效,<br/> * 經過動態刷新配置不會產生效果.避免出現運行期監測數據丟失的狀況. **/ public static final String METRICS_ROLLING_PERCENTILE_NUM_BUCKETS = "metrics.rollingPercentile.numBuckets"; /** * 配置在執行過程當中每一個"桶"中保留的最大執行次數: 默認100<br/> * 若是在滾動時間窗內超過該設定值的執行次數,就從最初的位置開始重寫<br/> * 增長該值的大小會增長內存量的消耗,並增長排序百分位數所需的計算時間<br/> * 該屬性從Hystrix 1.4.12版本開始,只有在應用初始化的時候生效,<br/> * 經過動態刷新配置不會產生效果.避免出現運行期監測數據丟失的狀況. **/ public static final String METRICS_ROLLING_PERCENTILE_BUCKET_SIZE = "metrics.rollingPercentile.bucketSize"; /** * 配置採集影響斷路器狀態的健康快照(請求的成功,錯誤百分比)的間隔等待時間: 默認500ms **/ public static final String METRICS_HEALTH_SNAPSHOT_INTERVAL_IN_MILLISECONDS = "metrics.healthSnapshot.intervalInMilliseconds"; } /** * hystrix request context 配置 * * @see com.netflix.hystrix.strategy.concurrency.HystrixRequestContext * @see com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand#commandProperties() * @see com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty **/ public static class RequestContextConstants { /** * 配置是否開啓請求緩存: 默認爲true * * @see com.netflix.hystrix.HystrixRequestCache **/ public static final String REQUEST_CACHE_ENABLED = "requestCache.enabled"; /** * 配置HystrixCommand的執行和事件是否打印日誌到HystrixRequestLog: 默認爲true * * @see com.netflix.hystrix.HystrixRequestLog **/ public static final String REQUEST_LOG_ENABLED = "requestLog.enabled"; } /** * hystrix collapser constants * * @see com.netflix.hystrix.HystrixCollapser * @see com.netflix.hystrix.contrib.javanica.annotation.HystrixCollapser * @see com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty **/ public static class CollapserConstants { /** * 配置一次請求合併並批處理中容許最大請求數: 默認Integer.MAX_VALUE **/ public static final String MAX_REQUESTS_IN_BATCH = "maxRequestsInBatch"; /** * 配置批處理過程當中每一個命令延遲時間: 默認10ms **/ public static final String TIMER_DELAY_IN_MILLISECONDS = "timerDelayInMilliseconds"; /** * 配置批處理過程當中是否開啓請求緩存 **/ public static final String REQUEST_CACHE_ENABLED = "requestCache.enabled"; } /** * hystrix command thread pool constants * * @see com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand#threadPoolProperties() * @see com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty **/ public static class ThreadPoolConstants { /** * 配置命令線程池的核心線程數,命令執行最大併發量: 默認10 **/ public static final String CORE_SIZE = "coreSize"; /** * maximum size of thread pool: 默認10 **/ public static final String MAXIMUM_SIZE = "maximumSize"; /** * 配置線程池的最大隊列大小: 默認-1<br/> * 配置-1,線程池使用{@link java.util.concurrent.SynchronousQueue}實現的隊列,<br/> * 不然使用{@link java.util.concurrent.LinkedBlockingQueue} **/ public static final String MAXQUEUE_SIZE = "maxQueueSize"; /** * 配置隊列拒絕閾值.配置該參數,即便隊列沒有達到最大值也拒絕請求: 默認5<br/> * 當maxQueueSize=-1,該配置不生效 **/ public static final String QUEUE_SIZE_REJECTION_THRESHOLD = "queueSizeRejectionThreshold"; /** * minutes to keep a thread alive: 默認1分鐘(60s) **/ public static final String KEEP_ALIVE_TIMEMINUTES = "keepAliveTimeMinutes"; /** * should the maximumSize config value get read and used in configuring the threadPool * turning this on should be a conscious decision by the user, so we default it to false: 默認false **/ public static final String ALLOW_MAXIMUM_SIZE_TO_DIVERGE_FROM_CORE_SIZE = "allowMaximumSizeToDivergeFromCoreSize"; /** * 配置滾動時間窗的牀都,單位ms: 默認10000(10s)<br/> * 該滾動時間窗的長度用於線程池的指標度量,分紅多個"桶"統計指標 **/ public static final String METRICS_ROLLING_STATS_TIME_IN_MILLISECONDS = "metrics.rollingStats.timeInMilliseconds"; /** * 配置滾動時間窗被劃分紅"桶"的數量: 默認10<br/> * metrics.rollingStats.timeInMilliseconds必須能被該參數整除,否則拋出異常 **/ public static final String METRICS_ROLLINGSTATS_NUMBUCKETS = "metrics.rollingStats.numBuckets"; } }