斷路器真的有效嗎?重試會讓情況更糟糕! - brooker

banq發表於2022-03-09

現代分散式系統被設計為允許發生系統中一部分故障,即使不能取悅所有人,也會繼續為一些客戶提供服務。

而斷路器的設計是為了將部分故障變成完全故障。

這屬於:一種機制可能會打敗另一種機制。

在部署斷路器之前,請確保你考慮清楚這一點:

重試(大多數情況下)會使實際分散式系統中的情況變得更糟。

  

斷路器充當可能失敗的操作的代理。代理應該監視最近發生的失敗次數,並使用這些資訊來決定是允許操作繼續進行,還是直接返回異常。

來自Martin Fowler):

斷路器背後的基本思想非常簡單。您將受保護的函式呼叫包裝在斷路器物件中,該物件監視故障。一旦故障達到某個閾值,斷路器就會跳閘,並且對斷路器的所有進一步呼叫都會返回錯誤,而根本不會進行受保護的呼叫。

馬丁富勒再次認為:

軟體系統對執行在不同程式中的軟體進行遠端呼叫是很常見的,可能在網路上的不同機器上。記憶體呼叫和遠端呼叫之間的一大區別是遠端呼叫可能會失敗,或者掛起而沒有響應,直到達到某個超時限制。更糟糕的是,如果您的供應商有很多呼叫者沒有響應,那麼您可能會耗盡關鍵資源,從而導致跨多個系統的級聯故障。

微軟:

請注意,設定更短的超時可能有助於解決此問題,但超時不應太短以至於操作在大多數情況下都會失敗,即使對服務的請求最終會成功。

 

當人們談論斷路器時,他們通常會考慮兩個潛在的好處:

  • 正如 Martin 指出的那樣,其中之一是儘早失敗可以防止您將工作或資源浪費在註定要失敗的事情上。這樣做可能允許需要相同資源但不依賴於相同下游依賴項的工作繼續成功。
  • 第二個好處是允許服務中的一種漸進式退化。

 

斷路器的問題

斷路器的問題在於它們沒有考慮到真實分散式系統的基本屬性。讓我們考慮一個玩具分散式 NoSQL 資料庫的架構

有一個路由器層和一些分片儲存noSQL資料庫:當請求以 B 開頭的Key進入時,它會進入 AH 分片。對以 T 開頭的Key的請求轉到 SZ 分片,依此類推。

實際系統往往比這更復雜和更復雜,但橫向擴充套件資料庫的頂級架構幾乎總是看起來有點像這樣。

這個系統怎麼會失敗?顯然,路由器層可能無法將整個事情搞砸。但這似乎不太可能,因為它很簡單,可能是無狀態的,易於水平擴充套件等。

更有可能是其中一個儲存分片過載:

假設AaronCon在城裡,每個人都在嘗試註冊,導致AH 分片會得到很多負載,而其他分片可能會得到很少。

因為AH分片儲存有很高負載,對 AH 的呼叫可能會開始失敗,而對其他鍵key的呼叫會繼續工作。

這就給斷路器帶來了一個問題。這個資料庫壞了嗎?失敗是否達到了一個閾值?

如果你說是的,它壞了,那麼你就使Jane和Tracy的服務變得更糟。

如果你說沒有,它沒有壞,那麼你可能根本就沒有斷路器。不跳閘的斷路器不是很有用。

同樣的問題也適用於基於單元的架構,一個單元的故障導致斷路器跳閘,可能會使整個系統看起來像癱瘓了一樣,完全違背了單元的目的。基於單元的架構類似於分片的架構,只是為了可用性和爆炸半徑而不是規模而分片。

 

 

我們能解決這些問題嗎?

也許可以。這裡的問題是,在基於單元(微服務)和分片的系統中,斷路器要做正確的事情,它們需要預測一些非常具體的東西:這些引數的這個呼叫是否可能成功?

從其他引數的呼叫中推斷出這一點可能是不可能的。客戶對他們所呼叫的系統的內部工作原理根本不瞭解(而且主要是不應該瞭解),無法做出這樣的決定。

通常情況下,對這個問題提出了三種解決方案。

  1. 緊密耦合:如果客戶端確實知道服務中的內部資料分片是如何工作的,它就可以看到服務中的哪些分片是壞的,並做出一個好的決定。顯然,這裡的權衡是,這種分層違規使改變變得困難。沒有人希望在不改變每個客戶的情況下無法改變他們的服務。另一方面,如果你能猜得夠準,這種方法可能會很有效,就像每個上游客戶有斷路器一樣。
  2. 伺服器資訊:在過載時,服務可以說 "對於以A開頭的請求,我已經過載了",而客戶可以翻開相應的小型斷路器。我見過現實世界的系統是這樣工作的,但複雜性成本可能很高。
  3. 統計推理魔法/AI魔法/ML魔法:可以工作。很難做到正確。當到達的流量看起來與訓練集完全不一樣時,寫事後總結會很有趣。

 

相關文章