在微服務架構中,服務之間的依賴關係錯綜複雜,任何一個服務的中斷都可能引發連鎖反應,導致整個應用程式癱瘓。尤其在高流量情境下,第三方服務的失效可能迅速耗盡系統資源,造成嚴重後果。為避免此類別風險,匯入電路斷路器模式至關重要。電路斷路器模式的核心概念在於類別比電路中的斷路器,當偵測到服務異常時,立即切斷連線,防止錯誤蔓延。它有三種狀態:關閉狀態代表服務正常運作;開啟狀態表示服務異常,所有請求直接傳回錯誤;半開啟狀態則允許少量請求透過,用於測試服務是否還原正常。

服務中斷對應用程式的影響

當服務中斷發生時,對於消耗其服務的應用程式和終端使用者來說,可能會產生嚴重的後果。特別是在網路流量高峰期,如果一個無伺服器的微服務呼叫一個無回應的遠端應用程式,就會面臨以下風險:

  • 雲端資源快速達到其組態的配額或並發限制
  • Lambda 函式執行時間更長,等待回應同時也增加了成本
  • 一個服務的延遲觸發了應用程式範圍內的網格鎖現象

此外,如果你的服務是導向使用者的,當使用者在等待回應時可能會不耐煩地傳送更多請求,從而增加混亂並耗盡你的服務資源。在這種情況下,你需要有一種方法來評估服務提供者的健康狀態,並快速失敗,而不是等待——實作電路斷路器模式可以幫助你限制損害。

電路斷路器實作的核心概念

瞭解電路斷路器的核心概念非常重要。它們包括:

1. 關閉電路

圖 5-11 顯示了一個簡單的服務,它從一個 SaaS 平臺中抓取客戶訂單詳細資訊,使用從使用者應用程式到第三方系統和傳回的同步請求/回應呼叫。該圖顯示了 Lambda 函式和第三方系統之間的連線按預期工作——它是一個關閉的電路。

2. 開放電路

當電路被標記為開放時,系統之間的連線就不會發生。在圖 5-12 中,當第三方系統下線或回應非常慢時,Lambda 函式無法成功處理其請求。在這種情況下,由於電路是開放的,函式不會呼叫第三方 SaaS 平臺,而是立即失敗並傳回錯誤。

3. 電路斷路器

電路斷路器(或管理器)是一個物件,它包裝了一個受保護的函式呼叫,並監視錯誤,使用其定義的邏輯來確定是否將電路(連線)標記為開放或關閉。這種確定通常取決於閾值條件:例如,在兩分鐘內連續五次失敗到達第三方系統可能導致電路斷路器將電路標記為開放。

4. 半開電路

電路斷路器需要有一種方法來確定何時可以再次將電路宣告為關閉。由於它無法知道外部應用程式是否已還原,因此典型的方法是等待一段時間然後允許少量呼叫透過。根據這些呼叫的成功或失敗以及電路斷路器邏輯,它然後 либо 將電路標記為關閉, либо 將其保持為開放狀態並設定一個新鮮的超時值以便再次檢查。這個半開電路允許電路斷路器「測試水溫」,如果你願意這樣說的話。

韌性架構:電路斷路器模式

截至目前,Lambda 服務不提供內建的電路斷路功能。因此,瞭解該模式及其實作至關重要。電路斷路器的確切實作邏輯將取決於你的使用案例。一般而言,你需要一個地方來儲存電路的當前狀態作為最低要求。此外,你可能還想儲存閾值計數器、超時值、嘗試次數等。根據外部系統的重要性及其對業務的更廣泛影響,你可能會選擇一個簡單的電路狀態檢查機制或一個專用的服務,如下一節所述。

1. 簡單狀態檢查函式

如果只有一個應用程式正在與第三方或外部服務互動,如圖 5-12 所示,你可以使用 Lambda 函式來檢查第三方的狀態並將狀態儲存在 AWS Systems Manager (SSM) Parameter Store 中的一個引數中,如圖 5-13 所示。

現在你有了一種方法來確定電路的狀態,訂單抓取服務可以在呼叫第三方系統之前合並狀態檢查,如圖 5-14 所示。

2. 專用的事件驅動狀態檢查服務

當你有一個關鍵微服務或一個為多個應用程式提供服務的外部第三方應用程式時,你可能想要實作一個專用的健康狀態檢查服務,如圖 5-15 所示。

如圖 5-15 所示,有幾個選項可用於實作狀態檢查功能;你可以根據你的使用案例和目的選擇適合的一個。以下是選擇正確的一個幾點思考:

  • 如果服務消費者都在同一個 AWS 帳戶中,則儲存當前狀態在 SSM 引數中以供檢查是一個簡單的選擇。
  • 一個更複雜的選擇是透過 API 端點以服務形式提供狀態檢查。
  • 雖然不是理想的,但一個簡單的方法是授予所有消費者讀取 DynamoDB 表中狀態專案的許可權。
  • 事件驅動方法受益於作為操作事件推播通知服務狀態。範例 5-1 顯示了一個這樣的事件可能看起來如何:
{
  "metadata": {
    "version": "1.0",
    "trace_id": "skdj834sd3-j3ns-cmass23",
    "created_at": "2023-12-30T10:15:03Z",
    "domain": "retail",
    "subdomain": "orders",
    "service": "status-checker",
    "category": "operational_event",
    "type": "status",
    "status": "down"
  },
  "data": {
    "system": "anytime-third-party",
    "current_status": "down",
    "previous_status": "up",
    "current_status_since": "2023-12-30T09:55:00Z",
    "last_checked_at": "2023-12-30T10:15:00Z"
  }
}

如果一個應用程式沒有提供專用的狀態檢查端點,呼叫一個端點來抓取一些測試資料而不會產生任何副作用是一個替代選擇。

如果你決定實作一個專用的狀態監控服務,有幾點需要注意:

  • 專用的狀態檢查端點的可用性 專業對第三方應用程式的週期性狀態檢查依賴於一個專用的健康狀態檢查 API。儘管大多數 SaaS 平臺提供這樣的功能,但你可能會發現一些沒有這個功能的傳統應用程式。
  • 對監控系統的潛在益處 具有專用的服務允許你在監控儀錶板上跟蹤外部系統的健康狀態,以供監控目的提供持續可見性。此外,它使你能夠在必要時提醒你的值班支援工程師。
  • API 配額和呼叫限制

圖表翻譯:

  graph LR
    A[開始] --> B[檢查第三方系統狀態]
    B --> C[呼叫第三方系統]
    C --> D[處理回應]
    D --> E[傳回結果]

內容解密:

以上所述是實作電路斷路器模式以處理第三方系統中斷的一種方法。透過使用狀態檢查機制和專用的健康狀態檢查服務,可以提高應用程式對外部依賴性的韌性,並減少由第三方系統中斷引起的影響。

服務狀態檢查的重要性

在設計服務架構時,服務狀態檢查是一個至關重要的組成部分。它可以幫助我們確保服務的可用性和穩定性,避免不必要的請求和資源浪費。下面,我們將探討服務狀態檢查的實作方式和優點。

服務狀態檢查模式

服務狀態檢查模式是一種設計模式,允許多個應用程式透過一個統一的端點查詢外部系統的狀態。這種模式可以幫助我們避免多次請求外部系統,減少資源浪費和提高效率。

集中式服務狀態檢查

集中式服務狀態檢查是一種實作方式,透過一個專門的服務來查詢外部系統的狀態。這種方式可以幫助我們統一管理外部系統的狀態,避免多次請求和資源浪費。

分散式服務狀態檢查

分散式服務狀態檢查是一種實作方式,允許個別應用程式查詢外部系統的狀態。這種方式可以幫助我們提高效率和減少資源浪費,但需要更多的管理和維護工作。

快速失敗的優點

快速失敗是一種設計模式,允許應用程式在外部系統無法回應請求時快速傳回錯誤回應。這種模式可以幫助我們提高使用者滿意度,減少計算資源浪費和降低風險。

使用者滿意度

快速失敗可以幫助我們提高使用者滿意度,因為使用者可以快速得到回應,避免長時間等待。

減少計算資源浪費

快速失敗可以幫助我們減少計算資源浪費,因為當外部系統無法回應請求時,應用程式可以快速傳回錯誤回應,避免長時間等待和資源浪費。

降低風險

快速失敗可以幫助我們降低風險,因為當外部系統無法回應請求時,應用程式可以快速傳回錯誤回應,避免過度負載和資源耗盡。

儲存請求和重播

儲存請求和重播是一種設計模式,允許應用程式在外部系統無法回應請求時儲存請求,並在外部系統還原後重播請求。這種模式可以幫助我們提高可靠性和可用性,避免資料丟失和錯誤。

儲存請求

儲存請求是一種實作方式,允許應用程式在外部系統無法回應請求時儲存請求。這種方式可以幫助我們避免資料丟失和錯誤,提高可靠性和可用性。

重播請求

重播請求是一種實作方式,允許應用程式在外部系統還原後重播儲存的請求。這種方式可以幫助我們提高可靠性和可用性,避免資料丟失和錯誤。

圖表翻譯:

上述流程圖描述了服務狀態檢查的流程。首先,開始服務狀態檢查(A)。然後,進行快速失敗(B)的檢查,如果外部系統無法回應請求,則傳回錯誤回應。接下來,儲存請求(C)以便在外部系統還原後重播。如果儲存請求成功,則重播請求(D)。最後,結束流程(E)。

  sequenceDiagram
    participant 服務狀態檢查
    participant 快速失敗
    participant 儲存請求
    participant 重播請求
    Note over 服務狀態檢查,快速失敗: 服務狀態檢查失敗
    服務狀態檢查->>快速失敗: 傳回錯誤回應
    Note over 快速失敗,儲存請求: 儲存請求
    快速失敗->>儲存請求: 儲存請求
    Note over 儲存請求,重播請求: 重播請求
    儲存請求->>重播請求: 重播請求

內容解密:

上述序列圖描述了服務狀態檢查、快速失敗、儲存請求和重播請求之間的互動作用。首先,服務狀態檢查傳送一個請求給快速失敗。如果快速失敗傳回錯誤回應,則儲存請求被觸發。儲存請求成功後,重播請求被觸發以重播儲存的請求。這個流程確保了服務的可用性和穩定性,避免不必要的請求和資源浪費。

從系統架構的韌性設計角度來看,本文深入探討了服務中斷對應用程式造成的 cascading failure 風險,並提出了以電路斷路器模式作為解決方案的核心概念。分析了電路斷路器的不同狀態(關閉、開啟、半開)以及其運作機制,並比較了簡單狀態檢查函式和專用事件驅動狀態檢查服務兩種實作方式,尤其針對後者,詳細闡述了不同狀態儲存方案的選型考量,例如利用 SSM Parameter Store、API 端點、DynamoDB 表,以及事件驅動架構下的事件推播機制,展現了多維度的實務思維。然而,電路斷路器並非萬靈丹,其閾值設定、狀態檢查頻率以及 fallback 機制的設計都需根據具體業務場景仔細權衡,才能避免過度敏感或反應遲鈍,造成不必要的效能損耗或錯誤觸發。展望未來,隨著 Serverless 架構的普及和微服務之間依賴關係的日益複雜,預期電路斷路器模式將成為建構高用性、高韌性分散式系統的標準實踐。對於追求系統穩定性的開發團隊而言,深入理解並妥善運用電路斷路器模式,將是應對服務中斷挑戰,保障業務連續性的關鍵所在。玄貓認為,在匯入電路斷路器模式時,除了技術面的考量,更應結合業務指標和監控資料,持續最佳化其組態引數,才能最大程度發揮其效用。