Hystrix問題記錄
考慮這樣一個場景,先new了一個Command(commandKey="commandA"),他的隔離策略是訊號量隔離(ExecutionIsolationStrategy.SEMAPHORE),之後又new了一個Command(commandKey="commandA"),不過它的隔離策略是執行緒隔離(ExecutionIsolationStrategy.THREAD),那麼問題來了,這個新的command究竟是哪個隔離策略呢?
還是訊號量隔離,因為Hystrix有針對commandKey的快取。
當nenw一個新的command的引數設定階段(也就是AbstractCommand.initCommandProperties方法)時,會優先檢視快取裡commandKey是否已經存在,如果存在直接返回。
[圖片上傳失敗...(image-43d75f-1539487185510)]
2、訊號量隔離(semaphore-isolated)的超時處理
Hystrix的官方wiki上說的是“This allows Hystrix to shed load without using thread pools but it does not allow for timing out and walking away.”。這句話讓我產生了誤解, 其實他的意思並不是說訊號量隔離不支援超時,而是不支援超時之後立刻返回。
其實很好理解,因為訊號量隔離並沒有使用執行緒池,所以這個command執行的執行緒就是caller的執行緒,所以沒有辦法中斷這個執行緒,甚至我們可以說,這樣做是極度不安全的,因為可能會中斷應用執行緒。
那麼,如果使用了訊號量隔離,並且配置了超時時間1s,那麼如果超時了5s,會發生什麼呢?
這個command還是會執行5s才回返回,不過返回的是getFallback返回的結果。
[圖片上傳失敗...(image-8f6fa0-1539487185510)]
相關閱讀: Netflix%2FHystrix%2Fissues%2F835" rel="nofollow,noindex">ExecutionIsolationStrategy.SEMAPHORE and interrupt-on-timeout
3、執行緒隔離下的getFallback在哪個執行緒裡執行



這幾張圖其實不是我想說明這個問題而截得,不過正好也可以用來說明,這裡總結下。
- 如果是正常的執行,拋異常,那麼getFallback是在我們定義的執行緒池中執行;
- 如果是因為超時被中斷,那麼getFallback是在Timer的執行緒池(這是Hystrix自己的一個執行緒池,專門跑定時任務,用來計時)中執行;
- 如果已經被熔斷了,那麼getFallback是在caller所在的執行緒中執行;
- 如果是command超出了佇列限制,那麼getFallback是在caller所在的執行緒中執行;
4、Hystrix執行失敗但不能進入fallback的問題
如果command執行方法丟擲的throwable是:
- StackOverflowError
- VirtualMachineError
- ThreadDeath
- LinkageError
中的Error,那麼Hystrix不會進入fallback方法,而會直接丟擲HystrixRuntimeException,因為這幾個Error被認為是 不可恢復錯誤 。
AbstractCommand.java
:



5、HystrixRuntimeException: Command fallback execution rejected.
異常全文是:
com.netflix.hystrix.exception.HystrixRuntimeException: TestCommand fallback execution rejected. 複製程式碼
執行錯誤了,本應該去執行fallback方法,可是卻被reject了,為什麼呢?
這種情況下,一般來說是command已經熔斷了,所有請求都進入fallback導致的,因為fallback預設是有個併發最大處理的限制, fallback.isolation.semaphore.maxConcurrentRequests ,預設是10,這個方法及時很簡單,處理很快,可是QPS如果很高,還是很容易達到10這個閾值,導致後面的被拒絕。
解決方法也很簡單:
- fallback儘可能的簡單,不要有耗時操作,如果用一個http介面來作為另一個http介面的降級處理,那你必須考慮這個http是不是也會失敗;
- 可以適當增大 fallback.isolation.semaphore.maxConcurrentRequests
如果關心具體處理邏輯的話,可以看下 AbstractCommand.getFallbackOrThrowException