斷路器模式 - AWS 規定指引

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

斷路器模式

意圖

斷路器模式可以防止呼叫者服務在呼叫先前造成重複逾時或失敗時重試對另一個服務(被呼叫者)的呼叫。該模式還用於檢測被調用者服務何時再次正常工作。

動機

當多個微服務共同作業來處理請求時,一或多個服務可能無法使用或出現高延遲。當複雜的應用程式使用微服務時,一個微服務中斷可能導致應用程式失敗。微服務會透過遠端程序呼叫進行通訊,網路連線中可能會發生暫時性錯誤,進而導致失敗。(暫時性錯誤可以通過使用帶有輪詢模式的重試來處理。) 在同步執行期間,超時或失敗的級聯可能會導致使用者體驗不佳。

但是,在某些情況下,失敗可能需要更長的時間才能解決 — 例如,當被呼叫服務關閉或資料庫爭用導致逾時時。在這種情況下,如果呼叫服務重試呼叫,這些重試可能會導致網路爭用和資料庫執行緒集區消耗。此外,如果多個使用者重試應用程式,這會使問題變得更糟,並可能導致整個應用程式的效能降低。

斷路器模式是由邁克爾·尼加德在他的書推廣, 釋放它 (新年 2018). 此設計模式可防止呼叫者服務重試先前導致重複逾時或失敗的服務呼叫。它還可以檢測被呼叫者服務何時再次運行。

斷路器物體的工作方式就像電氣斷路器一樣,當電路中存在異常時會自動中斷電流。電氣斷路器關閉,或跳閘,當有故障電流的流動。同樣地,斷路器物件位於呼叫者和被呼叫者服務之間,如果被呼叫者不可用,則會跳閘。

分佈式計算的謬誤是一組由彼得德意志和其他人在 Sun 微系統提出的斷言。他們說,對分佈式應用程序新手的程序員總是會做出錯誤的假設。網路可靠性、預期零延遲和頻寬限制,使得軟體應用程式以最少的網路錯誤處理方式撰寫。

在網路中斷期間,應用程式可能會無限期地等待回覆,並持續耗用應用程式資源。無法在網路可用時重試作業,也可能導致應用程式降級。如果因為網路問題而API呼叫資料庫或外部服務逾時,沒有斷路器的重複呼叫可能會影響成本和效能。

適用性

在以下情況下使用此模式

  • 呼叫者服務會撥打最有可能失敗的呼叫。

  • 被呼叫者服務所產生的高延遲時間 (例如,資料庫連線速度較慢時) 會導致被呼叫者服務逾時。

  • 呼叫者服務進行同步呼叫,但被呼叫者服務不可用或表現出高延遲。

問題和考量

  • 服務無關的實作:為了防止程式碼膨脹,我們建議您以與微服務無關且驅動的方式來實作斷路器物件。API

  • 被呼叫者的電路封閉:當被呼叫者從性能問題或故障中恢復時,他們可以將電路狀態更新為。CLOSED這是斷路器模式的延伸,如果您的恢復時間目標 (RTO) 需要它,則可以實現。

  • 多執行緒呼叫:到期逾時值定義為在再次路由呼叫以檢查服務可用性之前,電路保持跳動的時間段。在多個執行緒中呼叫被呼叫服務時,第一個失敗的呼叫會定義到期逾時值。您的實施應確保後續調用不會無休止地移動到期超時。

  • 強制開啟或關閉電路:系統管理員應具備開啟或關閉電路的能力。這可以通過更新數據庫表中的到期超時值來完成。

  • 觀測性:應用程式應設定記錄,以識別斷路器開啟時失敗的呼叫。

實作

高層級架構

在下列範例中,來電者是訂單服務,被呼叫者是付款服務。

如果沒有故障,訂單服務會透過斷路器將所有呼叫路由至付款服務,如下圖所示。

斷路器模式,沒有故障。

如果支付服務逾時,斷路器可以檢測到超時並跟踪故障。

斷路器與支付服務失敗。

如果逾時超過指定的閾值,則應用程式會開啟電路。當電路開啟時,斷路器物件不會將呼叫路由到付款服務。當訂單服務調用付款服務時,它會立即返回失敗。

斷路器停止路由到付款服務。

斷路器物件會定期嘗試查看對付款服務的呼叫是否成功。

斷路器會定期重試付款服務。

當呼叫付款服務成功時,電路將關閉,並且所有進一步的呼叫都會再次路由到付款服務。

斷路器與工作支付服務。

使用 AWS 服務實施

範例解決方案使用中的快速工作流程AWS Step Functions來實作斷路器模式。Step Functions 狀態機器可讓您設定模式實作所需的重試功能和以決策為基礎的控制流程。

此解決方案也使用 Amazon DynamoDB 表格做為資料存放區,以追蹤電路狀態。這可以替換為記憶體內部資料存放區,例如 Amazon ElastiCache (RedisOSS),以獲得更好的效能。

當服務想要呼叫其他服務時,它會以被呼叫者服務的名稱啟動工作流程。工作流程會從 DynamoDB 表格取得斷路器狀態,該CircuitStatus表格會儲存目前效能降級的服務。如果CircuitStatus包含被呼叫者的未過期記錄,則電路處於開放狀態。「Step Functions」工作流程會立即傳回失敗,並以FAIL狀態結束。

如果CircuitStatus表格不包含被呼叫者的記錄或包含過期的記錄,則服務可運作。狀態機器定義中的ExecuteLambda步驟會呼叫透過參數值傳送的 Lambda 函數。如果呼叫成功,「Step Functions」工作流程會以SUCCESS狀態結束。

使用 AWS Step Functions 和 DynamoDB 進行斷路器實作。

如果服務呼叫失敗或發生逾時,應用程式會以指數輪詢來重試定義的次數。如果服務呼叫在重試之後失敗,工作流程會在CircuitStatus資料表中插入帶有 a 的服務的記錄ExpiryTimeStamp,而工作流程會以FAIL狀態結束。只要斷路器開啟,對相同服務的後續呼叫就會立即傳回故障。狀態機器定義中的Get Circuit Status步驟會根據ExpiryTimeStamp值檢查服務可用性。使用 DynamoDB 存留時間 (TTL) 功能會從CircuitStatus表格中刪除過期項目。

範本程式碼

下列程式碼使用 GetCircuitStatus Lambda 函數來檢查斷路器狀態。

var serviceDetails = _dbContext.QueryAsync<CircuitBreaker>(serviceName, QueryOperator.GreaterThan, new List<object> {currentTimeStamp}).GetRemainingAsync(); if (serviceDetails.Result.Count > 0) { functionData.CircuitStatus = serviceDetails.Result[0].CircuitStatus; } else { functionData.CircuitStatus = ""; }

下列程式碼顯示 Step Functions 工作流程中的 Amazon 州語言陳述式。

"Is Circuit Closed": { "Type": "Choice", "Choices": [ { "Variable": "$.CircuitStatus", "StringEquals": "OPEN", "Next": "Circuit Open" }, { "Variable": "$.CircuitStatus", "StringEquals": "", "Next": "Execute Lambda" } ] }, "Circuit Open": { "Type": "Fail" }

GitHub 儲存庫

如需此模式範例架構的完整實作,請參閱https://github.com/aws-samples/circuit-breaker-netcore-blog。 GitHub

部落格參考

相關內容