Hystrix是如何工做的

接上一篇:《Hystrix介紹html

流程圖

下面這幅圖至關重要git

稍微解釋一下上面的流程:github

  1. Construct a HystrixCommand or HystrixObservableCommand Object
  2. Execute the Command
  3. Is the Response Cached?
  4. Is the Circuit Open?
  5. Is the Thread Pool/Queue/Semaphore Full?
  6. HystrixObservableCommand.construct() or HystrixCommand.run()
  7. Calculate Circuit Health
  8. Get the Fallback
  9. Return the Successful Response

 

1. 構造一個HystrixCommand或者HystrixObservableCommand對象

第一步是構造一個HystrixCommand或HystrixObservableCommand對象來表示對依賴項的請求。例如:緩存

HystrixCommand command = new HystrixCommand(arg1, arg2);
HystrixObservableCommand command = new HystrixObservableCommand(arg1, arg2);

 2. 執行命令

 你能夠用下列四種中的任意一種方式執行命令:併發

  • execute() — 阻塞,直到收到響應或者拋出異常.
  • queue() — 返回一個Future
  • observe() — 訂閱表明響應的Observable
  • toObservable() — 返回一個Observable,當你訂閱它之後,將會執行Hystrix命令而且推送它的響應

execute()方法是同步執行的,它是調用queue().get()異步

queue()方法是異步執行的,它調用的是toObservable().toBlocking().toFuture()性能

因此最終每一個HystrixCommand都是一個Observable的實現ui

3. 響應是否已經被緩存?

若是請求在緩存中可用,而且該請求對應的響應在緩存中也是可用的,那麼緩存的這個響應將當即以一個Observable的形式被返回spa

4. 斷路器是否打開?

當你執行命令的時候,Hystrix檢查斷路器是不是開着的。若是是開着的,那麼Hystrix不會執行命令,而是路由到第8步執行回退邏輯。若是是關着的,將執行第5步,繼續檢查容量是否可用。線程

5. 線程池/隊列/信號量是否已經滿了?

若是這個命令所關聯的線程池和隊列(或者信號量)是否滿了,若是是,那麼Hystrix不會執行命令,而是當即路由到第8不執行回退邏輯

6. HystrixObservableCommand.construct() or HystrixCommand.run()

咱們知道對依賴的調用請求都是封裝成HystrixCommand或者HystrixObservableCommand執行的,而真正執行的邏輯是寫在HystrixObservableCommand.construct()或者HystrixCommand.run()中的:

  • HystrixCommand.run() — 返回一個響應或者拋出一個異常
  • HystrixObservableCommand.construct() — 返回一個Observable,而且推送響應或者發送一個onError通知

若是在執行run()或者construct()方法超時,那麼線程將拋出一個TimeoutException。

7. 計算電路健康

Hystrix報告成功、失敗、拒絕、超時給斷路器,斷路器維護一組計算統計的計數器。

斷路器用這些統計數據來決定何時應該「跳閘」,此時後續全部的請求都會被短路,直到一個恢復週期耗盡之後在第一次檢查某些健康檢查以後纔會打開電路。

(PS:想象一下生活中的漏電保護器,電壓太高時會自動跳閘,跳閘之後就沒電了,家用電器都用不了了,以後你能夠本身不去合上,固然前提是你不能再用那些大功率電器了,因而來電了)

8. 回退

當命令執行失敗時,Hystrix試圖恢復到您的fallback:當run()或者construct()拋出異常;當因爲斷路器跳閘致使命令被短路;當命令的線程池或隊列容量滿了;或者當命令執行超時。

在HystrixCommand的狀況下,爲了提供回退邏輯,你能夠實現HystrixCommand.getfallback(),它返回一個單一的回退值。

對於HystrixObservableCommand(),爲了提供回退邏輯,你須要實現hystrixobservablecomman.resumewithfallback(),它會返回一個Observable,這個Observable可能返回一個回退值或者多個值。

若是你沒有實現一個fallback方法,或者fallback它本身拋了一個異常,此時Hystrix仍然會返回一個Observable,可是這個Observable什麼都不會推送並當即發送一個onError通知。經過這個onError通知,形成命令失敗的異常會傳回給調用者。

9. 返回成功響應

若是Hystrix命令成功,它會返回響應給調用者,或者返回一個Observable。這取決於在第2步的時候你是若是調用命令的。

Circuit Breaker(斷路器)

下圖顯示了HystrixCommand或HystrixObservableCommand是如何與HystrixCircuitBreaker交互的,以及它的邏輯和決策流程,包括斷路器中計數器的行爲。

上面的流程能夠這樣描述:

  1. 假設整個電路的體積達到必定的閾值
  2. 假設錯誤百分比超過設定的錯誤百分比閾值
  3. 斷路器從CLOSED變成OPEN
  4. 當它打開時,通過這個斷路器的全部請求被短路
  5. 過了一段時間之後,下一個單個請求被容許經過(此時是半打開狀態)。若是這個請求失敗,在接下來的睡眠窗口期間斷路器保持OPEN狀態;若是這個請求成功,斷路器轉成CLOSED狀態;而後繼續執行第1步,如此反覆。

隔離

Hystrix使用隔板模式來隔離彼此的依賴關係,並限制對其中任何一個的併發訪問。

線程和線程池

Hystrix使用獨立的、每一個依賴項的線程池做爲約束任何給定依賴項的一種方式,所以底層執行的延遲只會使該池中的可用線程飽和。

線程池的好處

  1. 應用程序被徹底保護而不受失控的客戶端的影響。給定的依賴項的線程池能夠填滿,而不會影響應用程序的其他部分。
  2. 應用程序能夠接收新的客戶端請求
  3. 當失敗的客戶端再次恢復正常時,線程池將被清理,應用程序將當即恢復正常的性能
  4. 若是一個客戶端配置錯誤,線程池的健康將會很快地證實這一點(經過增長錯誤、延遲、超時、拒絕等),而且您能夠處理它(一般是經過動態屬性進行實時處理),而不會影響應用程序的功能。

Semaphores(信號量)

你能夠用信號量(或者計數器)來限制對任意依賴項併發調用的數量,代替用線程池的大小。

HystrixCommand 和 HystrixObservableCommand 在兩個地方支持用信號量:

  • Fallback:當Hystrix恢復fallbacks時它老是調用Tomcat的線程這樣作
  • Execution:若是設置屬性execution.isolation.strategy爲SEMAPHORE,那麼,Hystrix將使用信號量而不是線程來限制調用該命令的發父線程的並數量。

 

https://github.com/Netflix/Hystrix/wiki/How-it-Works

相關文章
相關標籤/搜索