微服務-熔斷機制

背景

因爲微服務間經過RPC來進行數據交換,因此咱們能夠作一個假設:在IO型服務中,假設服務A依賴服務B和服務C,而B服務和C服務有可能繼續依賴其餘的服務,繼續下去會使得調用鏈路過長,技術上稱1->N扇出git

å¾ç

問題

若是在A的鏈路上某個或幾個被調用的子服務不可用或延遲較高,則會致使調用A服務的請求被堵住,堵住的請求會消耗佔用掉系統的線程、io等資源,當該類請求愈來愈多,佔用的計算機資源愈來愈多的時候,會致使系統瓶頸出現,形成其餘的請求一樣不可用,最終致使業務系統崩潰github

  1. 服務器失敗影響服務質量服務器

  2. 超負荷致使整個服務失敗微信

  3. 服務失敗形成的雪崩效應app

å¾ç

å¾ç

å¾ç

熔斷

熔斷模式:這種模式主要是參考電路熔斷,若是一條線路電壓太高,保險絲會熔斷,防止火災。放到咱們的系統中,若是某個目標服務調用慢或者有大量超時,此時,熔斷該服務的調用,對於後續調用請求,不在繼續調用目標服務,直接返回,快速釋放資源。若是目標服務狀況好轉則恢復調用。負載均衡

定義裏面有幾個量化的地方框架

  1. 目標服務調用慢或者超時:開啓熔斷的閥值量化ide

能夠經過兩個維度:時間與請求數微服務

時間 多長時間內的超時請求達到多少,觸發熔斷ui

請求數 從服務啓動,超時請求數達到多少,觸發

這兩個維度都須要記錄超時請求數和統計總請求數

  1. 狀況好轉,恢復調用

如何量化狀況好轉:多長時間以後超時請求數低於多少關閉熔斷

熔斷狀態

å¾ç

三種狀態的切換

開 -- 半開 -- 關

:使用快速失敗返回,調用鏈結束

半開:當熔斷開啓一段時間後,嘗試階段

:調用正常

實現機制

能夠使用一段僞代碼表示:

//正常request
if( request is open) {
    //fastfail
} else if( request is halfopen) {
    if ( request success count > recoverySampleVolume) {
        //state --> close
    }
} 
//失敗request
if( request is failcount > requestVolumeThreshold && errorPercentage > threshold) {
    //close --> open
}

請求熔斷開啓時,直接快速失敗

是halfopen狀態,若是成功處理次數是否大於恢復配置,就關閉熔斷

若是失敗次數超過閥值,開啓熔斷

而對於open-->halfopen的轉換,能夠經過定時器主動觸發

具體實現

如今有不少開源的

failsafe:https://github.com/jhalterman/failsafe

Hystrix

個案實現

在沒有熔斷時,請求鏈路:

client --> request --> balance -- > handler

一個請求過來,經過負載均衡找到具體的server,再執行

加入熔斷後:

client --> request --> circuitBreakerfilter --> balance -- > handler

CircuitBreakerFilter過濾掉被熔斷的server,在負載均衡時,再也不被選中

  1. getAllServers() 獲取全部服務器列表

  2. 根據requestService,requestMethod獲取熔斷的servers

  • 從allserverList中剔除這些server

熔斷服務列表怎麼維護呢?

正常狀態 --> 熔斷狀態
1. 收到失敗請求(e.g.超時,系統異常)
2. 判斷此service是否配置了熔斷策略 map<serviceName,circuitBreakerpolicy>
    - 根據serviceName,method,serverInfo獲取CircuitBreakerCounter
    - counter對失敗次數+1
    - 此server是否在half open狀態  HalfOpenServersMap<serverName+method,serverList>
        - 在:若是失敗次數超過RecoverySampleVolume,openserversmap<servername+method,serverlist>進行put操做、並從HalfOpenServersMap中remove
        - 不在:請求數大於等於10筆(requestVolumeThreshold),且錯誤率達到60%(errorPercentage),openserversmap<servername+method,serverlist>進行put操做
熔斷狀態 --> 正常狀態
1. 收到請求
2. 判斷此service是否配置了熔斷策略 map<serviceName,circuitBreakerpolicy>
    - 根據serviceName,method,serverInfo獲取CircuitBreakerCounter
    - counter調用次數+1
    - 若half-open 狀態下的服務instance被調用次數超過取樣的sample數,從HalfOpenServersMap中remove
疑問
  1. 錯誤率怎麼計算?

  2. counter的實現

  3. 上面是close與open的轉換,怎麼轉換到halfopen?

錯誤率= 錯誤次數/請求次數

halfopen狀態

在上面的提到,被熔斷的服務,若是狀況好轉就會關閉熔斷!「狀況好轉」:何時去判斷狀況好轉,怎麼判斷狀況好轉兩方面

  1. 在加入到openserversmap時,同時開啓延遲時間窗口後的定時任務

  • 從openserversmap中移除,加入到halfOpenServersMap

counter實現

  1. 簡單點:AtomicLong,如當是halfopen時,使用這種簡單的計數器疊加

  2. 滑動時間窗口實現

VS 降級

提到熔斷,不得不起一降低級。二者的區別

有時語言真是乏力,不容易表達清楚,羅列一下

熔斷是框架提供,無論業務什麼樣,防止系統雪崩,都須要提供一下基本功能;而降級與業務有關,自動或手動。好比支付,有不少種支付方式,儲蓄卡,信用卡,支付寶,微信。若發現某一支付通道不穩定,或壓力過大,手動先關閉,這就是一種降級

由此可看出:

  1. 觸發緣由不太同樣,服務熔斷通常是某個服務(下游服務)故障引發,而服務降級通常是從總體負荷考慮;

  2. 管理目標的層次不太同樣,熔斷實際上是一個框架級的處理,每一個微服務都須要(無層級之分),而降級通常須要對業務有層級之分(好比降級通常是從最外圍服務開始)

  3. 實現方式不同

參考

微服務熔斷與隔離

CircuitBreaker

相關文章
相關標籤/搜索