1. 程式人生 > >微服務開發之熔斷器

微服務開發之熔斷器

一般在微服架構中,有一個元件角色叫熔斷器。顧名思義,熔斷器起的作用就是在特定的場景下關掉當前的通路,從而起到保護整個系統的效果。

在微服務架構中,一般我們的獨立服務是比較多的,每個獨立服務之間劃分責任邊界,並通過約定協議介面來進行通訊。當我們的呼叫鏈路複雜依賴多時,很可能會發生雪崩效應。

假設有這麼一個場景,有A, B, C, D四個獨立服務,A會依賴B,C,D;當D發生負載過高或網路異常等導致響應過慢或超時時,很可能A會因此堆積過多的等待連結,從而導致A的狀態也轉為異常,後面依賴到A的其他服務跟著發生鏈式反應,這將會導致大面積的服務不可用,即使本來是一些沒有依賴到B,C,D的服務。如下圖所示:
這裡寫圖片描述

這不是我們希望看到的結果,所以這個時候熔斷器可以派上用場。最簡單的做法,我們為每個依賴服務配置一個熔斷器開關,正常情況下是關閉的,也就是可以正常發起請求;當請求失敗(超時或者其他異常)次數超過預設值時,熔斷器自動開啟,這時所有經過這個熔斷器的請求都會直接返回失敗,並沒有真正到達所依賴的服務上。這時服務A本身仍然是能正常服務的, 如下圖所示:
這裡寫圖片描述

那麼熔斷器具體又是怎麼工作的呢?來看下,一個擁有基本功能的熔斷器的狀態機大體是這樣子的:
這裡寫圖片描述

主要在三種狀態中轉換:

  • 關閉狀態
    當熔斷器處於關閉狀態時,請求是可以被放行的;
    當熔斷器統計的失敗次數觸發開關時,轉為開啟狀態。
  • 開啟狀態
    當熔斷器處於開啟狀態時,所有請求都是不被放行的,直接返回失敗;
    只有在經過一個設定的時間視窗週期後,熔斷器才會轉換到半開狀態
  • 半開狀態
    當熔斷器處於半開狀態時,當前只能有一個請求被放行;
    這個被放行的請求獲得遠端服務的響應後,假如是成功的,熔斷器轉換為關閉狀態,否則轉換到開啟狀態。

最後,基於這個狀態機,我用Golang實現了一個只包含最基本功能的熔斷器:github.com/moxiaomomo/circuitbreaker, 有興趣可以參考一下,也歡迎指正。

主要用法如下:

// 建立一個熔斷器例項,指定熔斷時間視窗和失敗觸發開關閾值等
cbs := NewCirucuitBreaker(time.Second, 150
, 20) // 向熔斷器註冊command(可以理解為對應的服務請求id) testcmd := "call_serviceB" suc := cbs.RegisterCommandAsDefault(testcmd) // 向熔斷器報告當前command的執行結果(成功或失敗) cbs.Report(testcmd, false) cbs.Report(testcmd, true) // ... // 向熔斷器詢問當前該command是否能被執行 execAllow := cbs.AllowExec(testcmd)