Azure 應用程式的失敗模式分析
失敗模式分析 (FMA) 是透過識別系統中可能的失敗點來建立系統彈性的程序。 應該在架構和設計階段納入 FMA,讓您可以一開始就將失敗復原建置至該系統。
以下是執行 FMA 的一般程序:
識別系統中的所有元件。 包含外部相依性,例如識別提供者、第三方服務等等。
識別每個元件可能發生的潛在失敗。 單一元件可能有多個失敗模式。 例如,您應該分別考慮讀取失敗和寫入失敗,因為它們的影響和可能的風險降低步驟會有所不同。
根據失敗模式的整體風險為每個失敗模式評分。 考量下列因素:
- 失敗的可能性為何。 該失敗是否相對常見? 極其罕見? 您不需要確切的數字;目的是幫助確定優先順序。
- 就可用性、資料遺失、貨幣成本和業務中斷而言,該失敗對應用程式有什麼影響?
判斷應用程式將如何回應和復原每個失敗模式。 請考量成本和應用程式複雜度之間的權衡。
作為 FMA 程序的起點,本文包含潛在失敗模式及其風險降低步驟的目錄。 該目錄是由技術或 Azure 服務所整理,再加上應用程式層級設計的一般類別。 該目錄並不詳盡,但涵蓋許多核心 Azure 服務。
注意
失敗應該與錯誤區別。 失敗是系統內發生的意外事件,導致系統無法繼續正常運作。 例如,硬體故障導致網路分割就是失敗。 通常,需要對失敗進行干預或針對該類失敗進行特定的設計。 而錯誤則是正常作業中可預期的部分,在發生時會立即處理,系統將在發生錯誤後繼續以相同的功能運作。 例如,在輸入驗證期間探索到的錯誤,可以透過商務邏輯來處理。
應用程式服務
App Service 應用程式關閉。
偵測。 可能的原因:
預期的關機
- 操作員關閉該應用程式;例如,使用 Azure 入口網站。
- 該應用程式因為閒置而卸載。 (只有當
Always On
設定已停用時。)
非預期的關機
- 該應用程式當機。
- App Service VM 執行個體無法使用。
Application_End 記錄將捕捉應用程式網域的關機 (軟進程當機),這是唯一捕捉應用程式網域關閉的方式。
復原:
- 如果預期關機,請使用該應用程式的關機事件正常關機。 例如,在 ASP.NET 中,使用
Application_End
方法。 - 如果該應用程式在閒置時卸載,則會在下一個要求時自動重新啟動。 不過,您將會產生「冷啟動」成本。
- 若要防止應用程式在閒置時卸載,請在 Web 應用程式中啟用
Always On
設定。 請參閱在 Azure 應用程式服務中設定 Web 應用程式。 - 若要防止操作員關閉該應用程式,請使用
ReadOnly
層級設定資源鎖定。 請參閱使用 Azure Resource Manager 鎖定資源。 - 如果該應用程式當機或 App Service VM 無法使用,App Service 會自動重新啟動該應用程式。
診斷。 應用程式記錄和 Web 伺服器記錄。 請參閱在 Azure 應用程式服務中啟用 Web 應用程式的診斷記錄。
特定使用者重複提出錯誤的要求或過載系統。
偵測。 驗證使用者,並在應用程式記錄中包含使用者 ID。
復原:
- 使用 Azure API 管理 來節流使用者的要求。 請參閱以 Azure API 管理進行進階要求節流
- 封鎖該使用者。
診斷。 記錄所有驗證要求。
部署了錯誤的更新。
偵測。 透過 Azure 入口網站監視應用程式健全狀態 (請參閱監視 Azure Web 應用程式效能),或實作健全狀態端點監視模式。
復原:。 使用多個部署位置,並復原到最後一個已知良好的部署。 如需詳細資訊,請參閱基本 Web 應用程式。
Microsoft Entra ID
OpenID Connect 驗證失敗。
偵測。 可能的失敗模式包括:
- Microsoft Entra ID 無法使用,或因為網路問題而無法連線。 重新導向至驗證端點失敗,而 OpenID Connect 中介軟體會擲回例外狀況。
- Microsoft Entra 租用戶不存在。 重新導向至驗證端點會傳回 HTTP 錯誤碼,而 OpenID Connect 中介軟體會擲回例外狀況。
- 使用者無法驗證。 不需要偵測策略;Microsoft Entra ID 會處理登入失敗。
復原:
- 捕捉來自中介軟體的未處理例外狀況。
- 處理
AuthenticationFailed
事件。 - 將該使用者重新導向至錯誤頁面。
- 使用者重試。
Azure 搜尋服務
將資料寫入「Azure 搜尋服務」失敗。
偵測。 捕捉 Microsoft.Rest.Azure.CloudException
錯誤。
復原:
搜尋 .NET SDK 會在暫時性失敗後自動重試。 由用戶端 SDK 擲回的任何例外狀況都應該被視為非暫時性錯誤。
預設重試原則使用指數輪詢。 若要使用不同的重試原則,請在 SearchIndexClient
或 SearchServiceClient
類別上呼叫 SetRetryPolicy
。 如需詳細資訊,請參閱自動重試。
診斷。 使用搜尋流量分析。
從「Azure 搜尋服務」讀取資料失敗。
偵測。 捕捉 Microsoft.Rest.Azure.CloudException
錯誤。
復原:
搜尋 .NET SDK 會在暫時性失敗後自動重試。 由用戶端 SDK 擲回的任何例外狀況都應該被視為非暫時性錯誤。
預設重試原則使用指數輪詢。 若要使用不同的重試原則,請在 SearchIndexClient
或 SearchServiceClient
類別上呼叫 SetRetryPolicy
。 如需詳細資訊,請參閱自動重試。
診斷。 使用搜尋流量分析。
Cassandra
讀取或寫入節點失敗。
偵測。 捕捉例外狀況。 針對 .NET 用戶端,這通常是 System.Web.HttpException
。 其他用戶端可能會有其他例外狀況類型。 有關更多資訊,請參閱正確處理 Cassandra 錯誤。
復原:
- 每個 Cassandra 用戶端都有自有的重試原則和功能。 有關更多資訊,請參閱正確處理 Cassandra 錯誤。
- 使用機架感知部署,並將資料節點分散到整個容錯網域。
- 部署到具有本機仲裁一致性的多個區域。 如果發生非暫時性失敗,請轉移至另一個區域。
診斷。 應用程式記錄
雲端服務
Web 或背景工作角色意外關閉。
偵測。 會引發 RoleEnvironment.Stopping 事件。
復原。 覆寫 RoleEntryPoint.OnStop 方法以正常清除。 如需詳細資訊,請參閱處理 Azure OnStop 事件的正確方式 (部落格)。
Azure Cosmos DB
讀取資料失敗。
偵測。 捕捉 System.Net.Http.HttpRequestException
或 Microsoft.Azure.Documents.DocumentClientException
。
復原:
- SDK 會自動重試失敗的嘗試。 若要設定重試次數和最長等待時間,請設定
ConnectionPolicy.RetryOptions
。 用戶端引發的例外狀況超出重試原則,或不是暫時性錯誤。 - 如果 Azure Cosmos DB 對用戶端進行節流,則會傳回 HTTP 429 錯誤。 檢查
DocumentClientException
中的狀態碼。 如果您持續收到錯誤 429,建議考慮提高該集合的輸送量值。- 如果您使用 MongoDB API,該服務會在節流時傳回錯誤碼 16500。
- 當您使用支援可用性區域的區域時,請啟用區域備援。 當您使用區域備援時,Azure Cosmos DB 會在發生區域中斷時自動容錯移轉。 如需更多資訊,請參閱使用 Azure Cosmos DB 達到高可用性。
- 如果您要設計多區域解決方案,請跨兩個以上區域複寫 Azure Cosmos DB 資料庫。 所有複本都是可讀取的。 使用用戶端 SDK,指定
PreferredLocations
參數。 這是已排序的 Azure 區域清單。 所有讀取都將傳送到清單中的第一個可用區域。 如果該要求失敗,用戶端會依序嘗試清單中的其他區域。 如需詳細資訊,請參閱如何在適用於 NoSQL 的 Azure Cosmos DB 中設定全域散發。
診斷。 記錄用戶端上的所有錯誤。
寫入資料失敗。
偵測。 捕捉 System.Net.Http.HttpRequestException
或 Microsoft.Azure.Documents.DocumentClientException
。
復原:
- SDK 會自動重試失敗的嘗試。 若要設定重試次數和最長等待時間,請設定
ConnectionPolicy.RetryOptions
。 用戶端引發的例外狀況超出重試原則,或不是暫時性錯誤。 - 如果 Azure Cosmos DB 對用戶端進行節流,則會傳回 HTTP 429 錯誤。 檢查
DocumentClientException
中的狀態碼。 如果您持續收到錯誤 429,建議考慮提高該集合的輸送量值。 - 當您使用支援可用性區域的區域時,請啟用區域備援。 當您使用區域備援時,Azure Cosmos DB 會同步複寫可用性區域的所有寫入。 如需更多資訊,請參閱使用 Azure Cosmos DB 達到高可用性。
- 如果您要設計多區域解決方案,請跨兩個以上區域複寫 Azure Cosmos DB 資料庫。 如果主要區域失敗,則會將另一個區域升級以寫入。 容錯移轉也可以手動觸發。 SDK 會執行自動探索和路由,因此應用程式程式碼會在容錯移轉之後繼續運作。 在容錯移轉期間 (通常是在幾分鐘內完成),因為 SDK 會尋找新的寫入區域所以寫入作業會延遲較久。 如需詳細資訊,請參閱如何在適用於 NoSQL 的 Azure Cosmos DB 中設定全域散發。
- 本文件會被保留在備份佇列以作為後援,並在之後處理該佇列。
診斷。 記錄用戶端上的所有錯誤。
佇列儲存體
將訊息寫入 Azure 佇列儲存體持續失敗。
偵測。 在 N 次重試嘗試之後,寫入作業仍失敗。
復原:
- 將資料儲存在本機快取中,並在服務可供使用時將寫入轉送至儲存體。
- 建立次要佇列,並在主要佇列無法使用時寫入該佇列。
診斷。 使用儲存體計量。
該應用程式無法處理來自佇列的特定訊息。
偵測。 特定應用程式。 例如,訊息包含無效的資料,或商務邏輯因某些原因而失敗。
復原:
將該訊息移至個別的佇列。 執行個別流程來檢查該佇列中的訊息。
請考慮使用 Azure 服務匯流排傳訊佇列,此功能會提供用於此目的之無效信件佇列功能。
注意
如果您使用儲存體佇列搭配 WebJobs,WebJobs SDK 內建了有害訊息處理功能。 請參閱如何透過 WebJobs SDK 使用 Azure 佇列儲存體。
診斷。 使用應用程式記錄。
Azure Cache for Redis
從快取讀取失敗。
偵測。 捕捉 StackExchange.Redis.RedisConnectionException
。
復原:
- 重試暫時性失敗。 Azure Cache for Redis 支援內建重試。 有關詳細資訊,請參閱 Azure Cache for Redis 重試指引。
- 將非暫時性失敗視為快取遺漏,並回到原始資料來源。
診斷。 使用 Azure Cache for Redis 診斷。
寫入快取失敗。
偵測。 捕捉 StackExchange.Redis.RedisConnectionException
。
復原:
- 重試暫時性失敗。 Azure Cache for Redis 支援內建重試。 有關詳細資訊,請參閱 Azure Cache for Redis 重試指引。
- 如果該錯誤是非暫時性的,請將其忽略並讓其他交易稍後寫入快取。
診斷。 使用 Azure Cache for Redis 診斷。
SQL Database
無法連接到主要區域的資料庫。
偵測。 連接失敗。
復原:
啟用區域備援。 藉由啟用區域備援,Azure SQL 資料庫會自動在支援區域內的多個 Azure 可用性區域複寫您的寫入。 有關更多資訊,請參閱區域備援可用性。
啟用異地複寫。 如果您要設計多區域解決方案,請考慮啟用 SQL 資料庫作用中異地複寫。
必要條件:資料庫必須設定為作用中異地複寫。 請參閱 SQL 資料庫作用中異地複寫。
- 如果是查詢,請從次要複本讀取。
- 針對插入和更新,手動容錯移轉至次要複本。 請參閱起始 Azure SQL 資料庫的計劃性或非計劃性容錯移轉。
複本使用不同的連接字串,因此您必須更新應用程式中的連接字串。
用戶端在連接集區中用盡連接。
偵測。 捕捉 System.InvalidOperationException
錯誤。
復原:
- 重試作業。
- 作為風險降低計劃,請隔離每個使用案例的連接集區,讓一個使用案例無法主宰所有連接。
- 增加最大連接集區。
診斷。 應用程式記錄。
達到資料庫連結限制。
偵測。 Azure SQL 資料庫會限制並行背景工作、登入和工作階段的數量。 該限制取決於服務層級。 如需詳細資訊,請參閱 Azure SQL 資料庫資源限制。
若要偵測這些錯誤,請捕捉 System.Data.SqlClient.SqlException
並檢查 SqlException.Number
的值是否有 SQL 錯誤碼。 如需相關錯誤碼的清單,請參閱 SQL 資料庫用戶端應用程式的 SQL 錯誤碼:資料庫連結錯誤和其他問題。
復原。 這些錯誤會被視為暫時性錯誤,因此重試可能會解決該問題。 如果您持續遇到這些錯誤,請考慮縮放資料庫。
診斷。 - sys.event_log 查詢會傳回成功的資料庫連結、連接失敗和死結。
服務匯流排傳訊
從「服務匯流排」佇列讀取消息失敗。
偵測。 捕捉來自用戶端 SDK 的例外狀況。 「服務匯流排」例外狀況的基底類別是 MessagingException。 如果該錯誤是暫時性的,則 IsTransient
屬性為 true。
有關詳細資訊,請參閱服務匯流排傳訊例外狀況。
復原:
- 重試暫時性失敗。 請參閱服務匯流排重試指引。
- 無法傳遞給任何接收者的訊息會放置於無效信件佇列。 使用此佇列來查看無法接收哪些訊息。 無效信件佇列不會自動清除。 這些訊息會保留在該處,直到您明確擷取它們為止。 請參閱服務匯流排無效信件佇列概觀。
將訊息寫入「服務匯流排」佇列失敗。
偵測。 捕捉來自用戶端 SDK 的例外狀況。 「服務匯流排」例外狀況的基底類別是 MessagingException。 如果該錯誤是暫時性的,則 IsTransient
屬性為 true。
有關詳細資訊,請參閱服務匯流排傳訊例外狀況。
復原:
「服務匯流排」用戶端會在暫時性錯誤之後自動重試。 根據預設,它會使用指數輪詢。 在達到重試計數上限或逾時期間上限之後,用戶端會擲回例外狀況。 如需詳細資訊,請參閱服務匯流排重試指引。
如果超過佇列配額,用戶端會擲回 QuotaExceededException。 例外狀況訊息提供了更多詳細資訊。 在重試之前,先從佇列清空一些訊息,並考慮使用「斷路器」模式,以避免在超過配額時繼續重試。 此外,請確保未將 BrokeredMessage.TimeToLive 屬性設定太高。
在區域內,可以使用分割的佇列或主題來改善復原。 未分割的佇列或主題會指派給一個傳訊存放區。 如果無法使用此傳訊存放區,該佇列或主題上的所有作業都會失敗。 分割的佇列或主題會被分割到多個傳訊存放區。
使用區域備援自動複寫多個可用性區域之間的變更。 如果一個可用性區域失敗,就會自動發生容錯移轉。 有關詳細資訊,請參閱使應用程式免受服務匯流排中斷與災害影響的最佳做法。
如果您要設計多區域解決方案,請在不同的區域中建立兩個「服務匯流排」命名空間,並複寫這些訊息。 您可以使用主動式複寫或被動式複寫。
- 主動式複寫:用戶端會將每個訊息傳送至這兩個佇列。 接收者會接聽這兩個佇列。 使用唯一識別碼標記訊息,讓用戶端可以捨棄重複的訊息。
- 被動式複寫:用戶端會將訊息傳送至一個佇列。 如果發生錯誤,用戶端會回復至另一個佇列。 接收者會接聽這兩個佇列。 此方法可減少傳送之重複訊息的數目。 不過,接收者仍必須處理重複的訊息。
如需詳細資訊,請參閱 GeoReplication 範例和使應用程式免受服務匯流排中斷與災害影響的最佳做法。
重複訊息。
偵測。 檢查訊息的 MessageId
和 DeliveryCount
屬性。
復原:
可能的話,請將訊息處理作業設計為等冪。 否則,儲存已經處理之訊息的訊息 ID,並在處理訊息之前檢查該 ID。
透過建立將
RequiresDuplicateDetection
設定為 true 的佇列來啟用重複偵測。 使用此設定,「服務匯流排」會自動刪除與上一條訊息具有相同MessageId
的任何訊息。 請注意以下要點:- 此設定可防止將重複的訊息放入佇列中。 它不會防止接收者多次處理相同的訊息。
- 重複資料偵測具有時間範圍。 如果重複資料傳送到此視窗以外,則不會偵測到。
診斷。 記錄重複的訊息。
該應用程式無法處理來自佇列的特定訊息。
偵測。 特定應用程式。 例如,訊息包含無效的資料,或商務邏輯因某些原因而失敗。
復原:
需要考量兩種失敗模式。
- 接收者偵測失敗。 在這種情況下,請將該訊息移動到無效信件佇列。 稍後,執行個別的程序來檢查無效信件佇列中的訊息。
- 接收者在處理訊息時失敗,例如,由於未處理的例外狀況。 若要處理此案例,請使用
PeekLock
模式。 在此模式中,如果鎖定過期,其他接收者就可使用該訊息。 如果訊息超過傳遞計數上限或存留時間,該訊息會自動移至無效信件佇列。
如需詳細資訊,請參閱服務匯流排寄不出的信件佇列的概觀。
診斷。 每當應用程式將訊息移至無效信件佇列時,就會將事件寫入應用程式記錄。
儲存體
將資料寫入 Azure 儲存體失敗
偵測。 用戶端會在寫入時收到錯誤訊息。
復原:
重試作業,以從暫時性失敗中復原。 用戶端 SDK 中的重試原則會自動處理此動作。
實作「斷路器」模式,以避免過度儲存。
如果 N 次重試嘗試失敗,請執行正常後援。 例如:
- 將資料儲存在本機快取中,並在服務可供使用時將寫入轉送至儲存體。
- 如果寫入動作位於交易範圍中,請補償該交易。
診斷。 使用儲存體計量。
從 Azure 儲存體讀取資料失敗。
偵測。 用戶端會在讀取時收到錯誤訊息。
復原:
- 重試作業,以從暫時性失敗中復原。 用戶端 SDK 中的重試原則會自動處理此動作。
- 針對RA-GRS 儲存體,如果從主要端點讀取失敗,請嘗試從次要端點讀取。 用戶端 SDK 可以自動處理此問題。 請參閱 Azure 儲存體複寫。
- 如果 N 次重試嘗試失敗,請採取後援動作以正常降級。 例如,如果無法從儲存體擷取產品映像,則顯示一般預留位置影像。
診斷。 使用儲存體計量。
虛擬機器
與後端 VM 的連接失敗。
偵測。 網路連接錯誤。
復原:
- 在負載平衡器後方的可用性設定組中部署至少兩個後端 VM。
- 如果連接錯誤是暫時性的,有時 TCP 會成功重試傳送該訊息。
- 在該應用程式中實作重試原則。
- 針對持續性或非暫時性錯誤,請實作斷路器模式。
- 如果呼叫的 VM 超過其網路輸出限制,將會填滿輸出佇列。 如果輸出佇列持續處於滿載狀態,請考慮擴充。
診斷。 記錄在服務界限的事件。
VM 執行個體無法使用或狀況不良。
偵測。 設定負載平衡器健全狀態探查,以指示 VM 執行個體的健全狀態。 探查應該檢查重要的功能是否正確回應。
復原。 針對每個應用程式層,將多個 VM 執行個體放入相同的可用性設定組中,並將負載平衡器放在 VM 前面。 如果健全狀態探查失敗,該負載均衡器將停止向狀況不良的執行個體傳送新連接。
診斷。 - 使用 Load Balancer 記錄分析。
- 設定監視系統以監視所有健全狀態監視端點。
操作員意外關閉 VM。
偵測。 N/A
復原。 使用 ReadOnly
層級設定資源鎖定。 請參閱使用 Azure Resource Manager 鎖定資源。
診斷。 使用 Azure 活動記錄。
WebJobs
當 SCM 主機閒置時,連續作業會停止執行。
偵測。 將取消權杖傳遞至 WebJob 函式。 如需詳細資訊,請參閱正常關機。
復原。 啟用 Web 應用程式中的 Always On
設定。 如需詳細資訊,請參閱搭配 WebJobs 執行背景工作。
應用程式設計
應用程式無法處理突增的傳入要求。
偵測。 取決於該應用程式。 一般徵兆:
- 網站會開始傳回 HTTP 5xx 錯誤碼。
- 相依服務,例如資料庫或儲存體,會開始節流要求。 視服務而定,尋找 HTTP 429 (要求太多) 之類的 HTTP 錯誤。
- HTTP 佇列長度會成長。
復原:
擴增以處理增加的負載。
緩解失敗,以避免串聯失敗破壞整個應用程式。 緩解策略包括:
診斷。 使用應用程式服務診斷記錄。 使用 Azure Log Analytics、Application Insights 或 New Relic 等服務來協助了解診斷記錄。
- 429 - 節流
- 408 - 逾時
- 401 - 未經授權
- 503 或 5xx - 服務無法使用
工作流程或分散式交易中的其中一個作業失敗。
偵測。 在 N 次重試嘗試之後,仍會失敗。
復原:
- 作為風險降低計劃,請實作排程器代理程式監督員模式來管理整個工作流程。
- 不要在逾時時重試。 此錯誤的成功率很低。
- 佇列工作,以便稍後重試。
診斷。 記錄所有作業 (成功且失敗),包括補償動作。 使用關聯性 ID,讓您可以追蹤相同交易內的所有作業。
對遠端服務的呼叫失敗。
偵測。 HTTP 錯誤碼。
復原:
- 重試暫時性失敗。
- 如果呼叫在 N 次嘗試之後失敗,請採取後援動作。 (特定應用程式。)
- 實作斷路器模式,以避免串聯失敗。
診斷。 記錄所有遠端呼叫失敗。
下一步
請參閱 Azure Well-Architected Framework 中的復原和相依性。 在開始進行架構和設計階段時就應該將失敗復原納入系統,以避免失敗風險。