Azure 應用程式的失敗模式分析

失敗模式分析 (FMA) 是一個程式,可藉由識別系統中可能的失敗點,在系統中建置復原能力。 FMA 應該是架構和設計階段的一部分,因此您可以從頭開始將失敗復原建置至系統。

以下是執行 FMA 的一般程式:

  1. 識別系統中的所有元件。 包含外部相依性,例如識別提供者、第三方服務等等。

  2. 針對每個元件,找出可能發生的潛在失敗。 單一元件可能有多個失敗模式。 例如,您應該另外考慮讀取失敗和寫入失敗,因為影響和可能的緩和步驟會有所不同。

  3. 根據失敗模式的整體風險來評分每個失敗模式。 考量下列因素:

    • 失敗的可能性為何。 這是相對常見的嗎? 極其罕見? 您不需要確切的數位;目的是協助排名優先順序。
    • 在可用性、數據遺失、貨幣成本和業務中斷方面,應用程式有何影響?
  4. 針對每個失敗模式,判斷應用程式將如何回應和復原。 請考慮成本與應用程式複雜性的取捨。

作為 FMA 程式的起點,本文包含潛在失敗模式及其風險降低步驟的目錄。 目錄是由技術或 Azure 服務所組織,再加上應用層級設計的一般類別。 目錄並不詳盡,但涵蓋許多核心 Azure 服務。

應用程式服務

App Service 應用程式關閉。

偵測。 可能的原因:

  • 預期的關機

    • 操作員關閉應用程式;例如,使用 Azure 入口網站。
    • 應用程式因為閑置而卸除。 (只有當設定已停用時 Always On 。)
  • 非預期的關機

    • 應用程式當機。
    • App Service VM 實例變得無法使用。

Application_End記錄會攔截應用程式網域關機(軟進程當機),也是攔截應用程式域關機的唯一方法。

復原:

  • 如果預期關機,請使用應用程式的關機事件正常關閉。 例如,在 ASP.NET 中,使用 Application_End 方法。
  • 如果應用程式在閑置時卸除,則會在下一個要求時自動重新啟動。 不過,您將會產生「冷啟動」成本。
  • 若要防止應用程式在閑置時卸除,請在 Web 應用程式中啟用 Always On 設定。 請參閱在 Azure App 服務 中設定 Web 應用程式。
  • 若要防止操作員關閉應用程式,請使用層級設定資源鎖定 ReadOnly 。 請參閱 使用 Azure Resource Manager 鎖定資源。
  • 如果應用程式當機或 App Service VM 變成無法使用,App Service 會自動重新啟動應用程式。

診斷。 應用程式記錄和 Web 伺服器記錄。 請參閱在 Azure App 服務 中啟用 Web 應用程式的診斷記錄。

特定用戶重複提出不正確的要求或多載系統。

偵測。 驗證使用者,並在應用程式記錄中包含使用者標識碼。

復原:

診斷。 記錄所有驗證要求。

部署了不正確的更新。

偵測。 透過 Azure 入口網站 監視應用程式健康情況(請參閱監視 Azure Web 應用程式效能),或實作健康情況端點監視模式

復原:。 使用多個 部署位置 ,並回復到最後一個已知良好的部署。 如需詳細資訊,請參閱 基本 Web 應用程式

Microsoft Entra ID

OpenID 連線 驗證失敗。

偵測。 可能的失敗模式包括:

  1. Microsoft Entra 識別碼無法使用,或因為網路問題而無法連線。 重新導向至驗證端點失敗,而 OpenID 連線 中間件會擲回例外狀況。
  2. Microsoft Entra 租使用者不存在。 重新導向至驗證端點會傳回 HTTP 錯誤碼,而 OpenID 連線 中間件會擲回例外狀況。
  3. 使用者無法驗證。 不需要偵測策略;Microsoft Entra ID 會處理登入失敗。

復原:

  1. 從中間件擷取未處理的例外狀況。
  2. 處理 AuthenticationFailed 事件。
  3. 將使用者重新導向至錯誤頁面。
  4. 使用者重試。

將數據寫入 Azure 搜尋服務失敗。

偵測。 攔截 Microsoft.Rest.Azure.CloudException 錯誤。

復原:

搜尋 .NET SDK 會在暫時性失敗後自動重試。 用戶端 SDK 擲回的任何例外狀況都應該視為非轉譯錯誤。

默認重試原則會使用指數輪詢。 若要使用不同的重試原則,請在 或 SearchServiceClient 類別上SearchIndexClient呼叫 SetRetryPolicy 。 如需詳細資訊,請參閱 自動重試

診斷。 使用 搜尋使用分析

從 Azure 搜尋服務讀取數據失敗。

偵測。 攔截 Microsoft.Rest.Azure.CloudException 錯誤。

復原:

搜尋 .NET SDK 會在暫時性失敗後自動重試。 用戶端 SDK 擲回的任何例外狀況都應該視為非轉譯錯誤。

默認重試原則會使用指數輪詢。 若要使用不同的重試原則,請在 或 SearchServiceClient 類別上SearchIndexClient呼叫 SetRetryPolicy 。 如需詳細資訊,請參閱 自動重試

診斷。 使用 搜尋使用分析

Cassandra

讀取或寫入節點失敗。

偵測。 攔截例外狀況。 針對 .NET 用戶端,這通常是 System.Web.HttpException。 其他用戶端可能會有其他例外狀況類型。 如需詳細資訊,請參閱 正確處理 Cassandra 錯誤。

復原:

  • 每個 Cassandra 用戶端 都有自己的重試原則和功能。 如需詳細資訊,請參閱 正確處理 Cassandra 錯誤。
  • 使用機架感知部署,並將數據節點分散到容錯網域。
  • 部署至具有本機仲裁一致性的多個區域。 如果發生非轉移失敗,請故障轉移至另一個區域。

診斷。 應用程式記錄檔

雲端服務

Web 或背景工作角色意外關閉。

偵測會引發 RoleEnvironment.Stopping 事件。

復原覆寫 RoleEntryPoint.OnStop 方法以正常清除。 如需詳細資訊,請參閱 處理 Azure OnStop 事件 的正確方式(部落格)。

Azure Cosmos DB

讀取數據失敗。

偵測。 Catch System.Net.Http.HttpRequestExceptionMicrosoft.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 中設定全域散發。

診斷。 記錄用戶端上的所有錯誤。

寫入數據失敗。

偵測。 Catch System.Net.Http.HttpRequestExceptionMicrosoft.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 SDK 會提供內建有害訊息處理。 請參閱 如何搭配 WebJobs SDK 使用 Azure 佇列記憶體。

診斷。 使用應用程式記錄。

Azure Cache for Redis

從快取讀取失敗。

偵測。 攔截 StackExchange.Redis.RedisConnectionException

復原:

  1. 在暫時性失敗時重試。 Azure Cache for Redis 支持內建重試。 如需詳細資訊,請參閱 Azure Cache for Redis 重試指導方針
  2. 將非傳輸失敗視為快取遺漏,並回復為原始數據源。

診斷。 使用 Azure Cache for Redis 診斷

寫入快取失敗。

偵測。 攔截 StackExchange.Redis.RedisConnectionException

復原:

  1. 在暫時性失敗時重試。 Azure Cache for Redis 支持內建重試。 如需詳細資訊,請參閱 Azure Cache for Redis 重試指導方針
  2. 如果錯誤為非交易,請忽略它,並讓其他交易稍後寫入快取。

診斷。 使用 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。

如需詳細資訊,請參閱 服務匯流排 傳訊例外狀況

復原:

  1. 在暫時性失敗時重試。 請參閱 服務匯流排 重試指導方針
  2. 無法傳遞至任何接收者的訊息會放在寄不出的信件佇列。 使用此佇列來查看無法接收哪些訊息。 沒有自動清除寄不出的信件佇列。 訊息會保留在該處,直到您明確擷取訊息為止。 請參閱 服務匯流排 寄不出的信件佇列概觀。

將訊息寫入 服務匯流排 佇列失敗。

偵測。 從用戶端 SDK 攔截例外狀況。 服務匯流排 例外狀況的基類是 MessagingException。 如果錯誤是暫時性的,則 IsTransient 屬性為 true。

如需詳細資訊,請參閱 服務匯流排 傳訊例外狀況

復原:

  • 服務匯流排 用戶端會在暫時性錯誤之後自動重試。 根據預設,它會使用指數輪詢。 在重試計數上限或逾時期間上限之後,用戶端會擲回例外狀況。 如需詳細資訊,請參閱 服務匯流排 重試指導方針

  • 如果超過佇列配額,用戶端會 擲回 QuotaExceededException。 例外狀況訊息會提供更多詳細數據。 在重試之前,先從佇列清空一些訊息,並考慮使用斷路器模式,以避免在超過配額時繼續重試。 此外,請確定 BrokeredMessage.TimeToLive 屬性未設定太高。

  • 在區域內,您可以使用分割的佇列或主題來改善復原能力。 未分割的佇列或主題會指派給一個傳訊存放區。 如果無法使用此傳訊存放區,該佇列或主題上的所有作業都會失敗。 分割的佇列或主題會分割到多個傳訊存放區。

  • 使用區域備援自動復寫多個可用性區域之間的變更。 如果一個可用性區域失敗,故障轉移就會自動發生。 如需詳細資訊,請參閱將應用程式與 服務匯流排 中斷和災害隔離的最佳做法。

  • 如果您要設計多區域解決方案,請在不同的區域中建立兩個 服務匯流排 命名空間,並復寫訊息。 您可以使用主動式複寫或被動複寫。

    • 作用中復寫:用戶端會將每個訊息傳送至這兩個佇列。 接收者會接聽這兩個佇列。 使用唯一標識符標記訊息,讓用戶端可以捨棄重複的訊息。
    • 被動復寫:用戶端會將訊息傳送至一個佇列。 如果發生錯誤,用戶端會回復至另一個佇列。 接收者會接聽這兩個佇列。 此方法可減少傳送的重複訊息數目。 不過,接收者仍必須處理重複的訊息。

    如需詳細資訊,請參閱 GeoReplication 範例將應用程式與 服務匯流排 中斷和災害隔離的最佳做法。

重複的訊息。

偵測MessageId檢查訊息的和 DeliveryCount 屬性。

復原:

  • 可能的話,請將訊息處理作業設計為等冪。 否則,儲存已經處理的訊息訊息標識碼,並在處理訊息之前檢查標識碼。

  • 建立設定為 true 的 RequiresDuplicateDetection 佇列,以啟用重複偵測。 使用此設定,服務匯流排 會自動刪除與上一個訊息一樣MessageId傳送的任何訊息。 請注意以下要點:

    • 此設定可防止將重複的訊息放入佇列中。 它不會防止接收者多次處理相同的訊息。
    • 重複偵測具有時間範圍。 如果重複項目傳送到此視窗以外,則不會偵測到。

診斷。 記錄重複的訊息。

應用程式無法處理來自佇列的特定訊息。

偵測。 應用程式專屬。 例如,訊息包含無效的數據,或商業規則因某些原因而失敗。

復原:

需要考慮兩種失敗模式。

  • 接收者會偵測失敗。 在此情況下,請將訊息移至寄不出的信件佇列。 稍後,執行個別的程式來檢查寄不出的信件佇列中的訊息。
  • 接收者在處理訊息時失敗,例如,由於未處理的例外狀況。 若要處理此案例,請使用 PeekLock 模式。 在此模式中,如果鎖定過期,訊息就會變成可供其他接收者使用。 如果訊息超過傳遞計數上限或存留時間,訊息會自動移至寄不出的信件佇列。

如需詳細資訊,請參閱服務匯流排寄不出的信件佇列的概觀

診斷。 每當應用程式將訊息移至寄不出的信件佇列時,請將事件寫入應用程式記錄。

儲存體

將數據寫入 Azure 儲存體 失敗

偵測。 用戶端會在寫入時收到錯誤。

復原:

  1. 重試作業,以從暫時性失敗中復原。 用戶端 SDK 中的重試原則會自動處理此動作。

  2. 實作斷路器模式,以避免大量儲存。

  3. 如果 N 次重試嘗試失敗,請執行正常後援。 例如:

    • 將數據儲存在本機快取中,並在服務可供使用時,稍後將寫入轉送至記憶體。
    • 如果寫入動作位於交易範圍中,請補償交易。

診斷。 使用 記憶體計量

從 Azure 儲存體 讀取數據失敗。

偵測。 用戶端會在讀取時收到錯誤。

復原:

  1. 重試作業,以從暫時性失敗中復原。 用戶端 SDK 中的重試原則會自動處理此動作。
  2. 針對RA-GRS 記憶體,如果從主要端點讀取失敗,請嘗試從次要端點讀取。 用戶端 SDK 可以自動處理此作業。 請參閱 Azure 儲存體 複寫
  3. 如果 N 次重試嘗試失敗,請採取後援動作以正常降級。 例如,如果無法從記憶體擷取產品映像,則顯示泛型佔位元元影像。

診斷。 使用 記憶體計量

虛擬機器

對後端 VM 的 連線 失敗。

偵測。 網路連線錯誤。

復原:

  • 在負載平衡器後方的可用性設定組中部署至少兩個後端 VM。
  • 如果連線錯誤是暫時性的,有時 TCP 會成功重試傳送訊息。
  • 在應用程式中實作重試原則。
  • 針對持續性或非傳輸錯誤,請實作 斷路器 模式。
  • 如果呼叫的 VM 超過其網路輸出限制,輸出佇列將會填滿。 如果輸出佇列一致已滿,請考慮相應放大。

診斷。 記錄服務界限的事件。

VM 實例變成無法使用或狀況不良。

偵測。 設定負載平衡器 健康情況探查 ,指出 VM 實例是否狀況良好。 探查應該檢查重要函式是否正確回應。

復原。 針對每個應用層,將多個 VM 實例放入相同的可用性設定組中,並將負載平衡器放在 VM 前面。 如果健康情況探查失敗,Load Balancer 會停止將新的聯機傳送至狀況不良的實例。

診斷。 - 使用 Load Balancer 記錄分析

  • 設定監視系統以監視所有健康情況監視端點。

操作員不小心關閉 VM。

偵測。 N/A

復原。 使用 ReadOnly 層級設定資源鎖定。 請參閱 使用 Azure Resource Manager 鎖定資源。

診斷。 使用 Azure 活動記錄

WebJobs

當 SCM 主機閒置時,連續作業會停止執行。

偵測。 將取消令牌傳遞至 WebJob 函式。 如需詳細資訊,請參閱 正常關機

復原Always On啟用 Web 應用程式中的設定。 如需詳細資訊,請參閱 使用 WebJobs 執行背景工作。

應用程式設計

應用程式無法處理傳入要求的尖峰。

偵測。 取決於應用程式。 一般徵兆:

  • 網站會開始傳回 HTTP 5xx 錯誤碼。
  • 相依服務,例如資料庫或記憶體,會開始節流要求。 視服務而定,尋找 HTTP 429 (要求太多)之類的 HTTP 錯誤。
  • HTTP 佇列長度會成長。

復原:

  • 相應放大以處理增加的負載。

  • 減少失敗,以避免串連失敗中斷整個應用程式。 風險降低策略包括:

    • 實作 節流模式 ,以避免壓倒性的後端系統。
    • 使用 佇列型負載撫平 來緩衝要求,並以適當的步調處理要求。
    • 排定特定客戶端的優先順序。 例如,如果應用程式具有免費和付費層,請對免費層的客戶進行節流,但不會對付費客戶進行節流。 請參閱 優先順序佇列模式

診斷。 使用 App Service 診斷記錄。 使用 Azure Log AnalyticsApplication InsightsNew Relic 等服務來協助了解診斷記錄。

您可以在這裡取得範例。 它會針對下列例外狀況使用 Polly

  • 429 - 節流
  • 408 - 逾時
  • 401 - 未經授權
  • 503 或 5xx - 服務無法使用

工作流程或分散式交易中的其中一個作業失敗。

偵測。 在 N 次重試嘗試之後,仍會失敗。

復原:

  • 作為風險降低計劃,請實 作排程器代理程式監督員 模式來管理整個工作流程。
  • 不要在逾時時重試。 此錯誤的成功率很低。
  • 佇列工作,以便稍後重試。

診斷。 記錄所有作業(成功且失敗),包括補償動作。 使用相互關聯標識碼,讓您可以追蹤相同交易內的所有作業。

遠端服務的呼叫失敗。

偵測。 HTTP 錯誤碼。

復原:

  1. 在暫時性失敗時重試。
  2. 如果呼叫在 N 次嘗試之後失敗,請採取後援動作。 (應用程式特定。)
  3. 實作 斷路器模式 ,以避免串聯失敗。

診斷。 記錄所有遠端呼叫失敗。

下一步

請參閱 Azure 架構完善的架構中的復原和相依性 。 從一開始就,建置失敗復原到系統中應該是架構和設計階段的一部分,以避免發生失敗的風險。