1. 程式人生 > >Hystrix原始碼解析--HystrixCircuitBreaker--思想層面(一)

Hystrix原始碼解析--HystrixCircuitBreaker--思想層面(一)

一、什麼是HystrixCircuitBreaker?

HystrixCircuitBreaker可以防止應用程式重複的嘗試呼叫容易失敗的依賴服務。HystrixCircuitBreaker的目的和Retry模式的目的是不同的。Retry模式令應用程式不斷的去重試呼叫依賴服務,直到最後成功。而HystrixCircuitBreaker是阻止應用程式繼續嘗試無意義的請求。HystrixCircuitBreaker可以按照如下的狀態來實現:

  • 關閉:應用程式的請求已經路由到了這個操作。HystrixCircuitBreaker應該維護最近一段時間的錯誤資訊,如果呼叫操作失敗,那麼大力增加這個錯誤資訊的數量。如果這個錯誤數量超過給定時間的閾值,HystrixCircuitBreaker進入到開啟狀態。這個時候,HystrixCircuitBreaker啟動一個超時的Timer,當Timer過期了,代理則進入半開狀態。超時Timer的目的是為了給依賴服務一段時間來自我修復之前碰到的問題。
  • 開啟:令可能失敗的外部呼叫操作立刻失敗,所有的外部呼叫直接拋異常給應用程式。
  • 半開:只有一定數量的應用請求可以進行操作的呼叫。如果這些請求成功了,那麼就假定之前發生的錯誤已經被依賴服務自動修復了,而HystrixCircuitBreaker轉換成關閉狀態,同時重置錯誤計數器。如果任何請求失敗了,那麼HystrixCircuitBreaker會假定錯誤仍然在存在,HystrixCircuitBreaker會重新轉換成開啟狀態,並重啟超時Timer給依賴服務更多的時間來自我修復錯誤。 

二、解決方法

HystrixCircuitBreaker可以防止應用程式不斷地嘗試執行可能會失敗的操作,使得應用程式繼續執行而不用等待修正錯誤,或者浪費CPU時間去等到長時間的超時產生。HystrixCircuitBreaker也可以使應用程式能夠診斷錯誤是否已經修正,如果已經修正,應用程式會再次嘗試呼叫操作。HystrixCircuitBreaker就像是那些容易導致錯誤的操作的一種代理。這種代理能夠記錄最近呼叫發生錯誤的次數,然後決定是否允許操作繼續,或者立即返回錯誤。

HystrixCircuitBreaker可以使用狀態機來實現,內部模擬以下幾種狀態。

  • 閉合(closed)狀態: 對應用程式的請求能夠直接引起方法的呼叫。代理類維護了最近呼叫失敗的次數,如果某次呼叫失敗,則使失敗次數加1。如果最近失敗次數超過了在給定時間內允許失敗的閾值,則代理類切換到斷開(Open)狀態。此時代理開啟了一個超時時鐘,當該時鐘超過了該時間,則切換到半斷開(Half-Open)狀態。該超時時間的設定是給了依賴服務恢復正常。
  • 斷開(Open)狀態:在該狀態下,對依賴服務的請求會立即返回錯誤響應。
  • 半斷開(Half-Open)狀態:允許對應用程式的一定數量的請求可以去呼叫依賴服務。如果這些請求對依賴服務的呼叫成功,那麼可以認為之前導致呼叫失敗的錯誤已經修正,此時Circuit-Breaker切換到閉合狀態,並且將錯誤計數器重置;如果這一定數量的請求有呼叫失敗的情況,則認為導致之前呼叫失敗的問題仍然存在,Circuit-Breaker切回到斷開方式,然後開始重置計時器來給依賴服務一定的時間來修正錯誤。半斷開狀態能夠有效防止正在恢復中的依賴服務被突然而來的大量請求再次拖垮。

各個狀態之間的轉換如下圖:

在Close狀態下,錯誤計數器是基於時間的。在特定的時間間隔內會自動重置。這能夠防止由於某次的偶然錯誤導致熔斷器進入斷開狀態。觸發熔斷器進入斷開狀態的失敗閾值只有在特定的時間間隔內,錯誤次數達到指定錯誤次數的閾值才會產生。在Half-Open狀態中使用的連續成功次數計數器記錄呼叫的成功次數。當連續呼叫成功次數達到某個指定值時,切換到閉合狀態,如果某次呼叫失敗,立即切換到斷開狀態,連續成功呼叫次數計時器在下次進入半斷開狀態時歸零。

實現熔斷器模式使得系統更加穩定和有彈性,在系統從錯誤中恢復的時候提供穩定性,並且減少了錯誤對系統性能的影響。它通過快速的拒絕那些試圖有可能呼叫會導致錯誤的服務,而不會去等待操作超時或者永遠不會不返回結果來提高系統的響應事件。如果熔斷器設計模式在每次狀態切換的時候會發出一個事件,這種資訊可以用來監控服務的執行狀態,能夠通知管理員在熔斷器切換到斷開狀態時進行處理。

可以對熔斷器模式進行定製以適應一些可能會導致遠端服務失敗的特定場景。比如,可以在熔斷器中對超時時間使用不斷增長的策略。在熔斷器開始進入斷開狀態的時候,可以設定超時時間為幾秒鐘,然後如果錯誤沒有被解決,然後將該超時時間設定為幾分鐘,依次類推。在一些情況下,在斷開狀態下我們可以返回一些錯誤的預設值,而不是丟擲異常。