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 App 服務 中設定 Web 應用程式。 - 若要防止操作員關閉應用程式,請使用層級設定資源鎖定
ReadOnly
。 請參閱 使用 Azure Resource Manager 鎖定資源。 - 如果應用程式當機或 App Service VM 變成無法使用,App Service 會自動重新啟動應用程式。
診斷。 應用程式記錄和 Web 伺服器記錄。 請參閱在 Azure App 服務 中啟用 Web 應用程式的診斷記錄。
特定用戶重複提出不正確的要求或多載系統。
偵測。 驗證使用者,並在應用程式記錄中包含使用者標識碼。
復原:
- 使用 Azure API 管理 來節流使用者的要求。 請參閱使用 Azure API 管理 進行進階要求節流
- 封鎖使用者。
診斷。 記錄所有驗證要求。
部署了不正確的更新。
偵測。 透過 Azure 入口網站 監視應用程式健康情況(請參閱監視 Azure Web 應用程式效能),或實作健康情況端點監視模式。
復原:。 使用多個 部署位置 ,並回復到最後一個已知良好的部署。 如需詳細資訊,請參閱 基本 Web 應用程式。
Microsoft Entra ID
OpenID 連線 驗證失敗。
偵測。 可能的失敗模式包括:
- Microsoft Entra 識別碼無法使用,或因為網路問題而無法連線。 重新導向至驗證端點失敗,而 OpenID 連線 中間件會擲回例外狀況。
- Microsoft Entra 租使用者不存在。 重新導向至驗證端點會傳回 HTTP 錯誤碼,而 OpenID 連線 中間件會擲回例外狀況。
- 使用者無法驗證。 不需要偵測策略;Microsoft Entra ID 會處理登入失敗。
復原:
- 從中間件擷取未處理的例外狀況。
- 處理
AuthenticationFailed
事件。 - 將使用者重新導向至錯誤頁面。
- 使用者重試。
Azure 搜尋服務
將數據寫入 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.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 中設定全域散發。
診斷。 記錄用戶端上的所有錯誤。
寫入數據失敗。
偵測。 Catch 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 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查詢會傳回成功的資料庫連線、連線失敗和死結。
- 建立 失敗連線的警示規則 。
- 啟用 SQL 資料庫 稽核並檢查失敗的登入。
服務匯流排傳訊
從 服務匯流排 佇列讀取訊息失敗。
偵測。 從用戶端 SDK 攔截例外狀況。 服務匯流排 例外狀況的基類是 MessagingException。 如果錯誤是暫時性的,則 IsTransient
屬性為 true。
如需詳細資訊,請參閱 服務匯流排 傳訊例外狀況。
復原:
- 在暫時性失敗時重試。 請參閱 服務匯流排 重試指導方針。
- 無法傳遞至任何接收者的訊息會放在寄不出的信件佇列中。 使用此佇列來查看無法接收哪些訊息。 沒有自動清除寄不出的信件佇列。 訊息會保留在該處,直到您明確擷取訊息為止。 請參閱 服務匯流排 寄不出的信件佇列概觀。
將訊息寫入 服務匯流排 佇列失敗。
偵測。 從用戶端 SDK 攔截例外狀況。 服務匯流排 例外狀況的基類是 MessagingException。 如果錯誤是暫時性的,則 IsTransient
屬性為 true。
如需詳細資訊,請參閱 服務匯流排 傳訊例外狀況。
復原:
服務匯流排 用戶端會在暫時性錯誤之後自動重試。 根據預設,它會使用指數輪詢。 在重試計數上限或逾時期間上限之後,用戶端會擲回例外狀況。 如需詳細資訊,請參閱 服務匯流排 重試指導方針。
如果超過佇列配額,用戶端會 擲回 QuotaExceededException。 例外狀況訊息會提供更多詳細數據。 在重試之前,先從佇列清空一些訊息,並考慮使用斷路器模式,以避免在超過配額時繼續重試。 此外,請確定 BrokeredMessage.TimeToLive 屬性未設定太高。
在區域內,您可以使用分割的佇列或主題來改善復原能力。 未分割的佇列或主題會指派給一個傳訊存放區。 如果無法使用此傳訊存放區,該佇列或主題上的所有作業都會失敗。 分割的佇列或主題會分割到多個傳訊存放區。
使用區域備援自動復寫多個可用性區域之間的變更。 如果一個可用性區域失敗,故障轉移就會自動發生。 如需詳細資訊,請參閱將應用程式與 服務匯流排 中斷和災害隔離的最佳做法。
如果您要設計多區域解決方案,請在不同的區域中建立兩個 服務匯流排 命名空間,並復寫訊息。 您可以使用主動式複寫或被動複寫。
- 作用中復寫:用戶端會將每個訊息傳送至這兩個佇列。 接收者會接聽這兩個佇列。 使用唯一標識符標記訊息,讓用戶端可以捨棄重複的訊息。
- 被動復寫:用戶端會將訊息傳送至一個佇列。 如果發生錯誤,用戶端會回復至另一個佇列。 接收者會接聽這兩個佇列。 此方法可減少傳送的重複訊息數目。 不過,接收者仍必須處理重複的訊息。
如需詳細資訊,請參閱 GeoReplication 範例和將應用程式與 服務匯流排 中斷和災害隔離的最佳做法。
重複的訊息。
偵測。 MessageId
檢查訊息的和 DeliveryCount
屬性。
復原:
可能的話,請將訊息處理作業設計為等冪。 否則,儲存已經處理的訊息訊息標識碼,並在處理訊息之前檢查標識碼。
建立設定為 true 的
RequiresDuplicateDetection
佇列,以啟用重複偵測。 使用此設定,服務匯流排 會自動刪除與上一個訊息一樣MessageId
傳送的任何訊息。 請注意以下要點:- 此設定可防止將重複的訊息放入佇列中。 它不會防止接收者多次處理相同的訊息。
- 重複偵測具有時間範圍。 如果重複項目傳送到此視窗以外,則不會偵測到。
診斷。 記錄重複的訊息。
應用程式無法處理來自佇列的特定訊息。
偵測。 應用程式專屬。 例如,訊息包含無效的數據,或商業規則因某些原因而失敗。
復原:
需要考慮兩種失敗模式。
- 接收者會偵測失敗。 在此情況下,請將訊息移至寄不出的信件佇列。 稍後,執行個別的程式來檢查寄不出的信件佇列中的訊息。
- 接收者在處理訊息時失敗,例如,由於未處理的例外狀況。 若要處理此案例,請使用
PeekLock
模式。 在此模式中,如果鎖定過期,訊息就會變成可供其他接收者使用。 如果訊息超過傳遞計數上限或存留時間,訊息會自動移至寄不出的信件佇列。
如需詳細資訊,請參閱服務匯流排寄不出的信件佇列的概觀。
診斷。 每當應用程式將訊息移至寄不出的信件佇列時,請將事件寫入應用程式記錄。
儲存體
將數據寫入 Azure 儲存體 失敗
偵測。 用戶端會在寫入時收到錯誤。
復原:
重試作業,以從暫時性失敗中復原。 用戶端 SDK 中的重試原則會自動處理此動作。
實作斷路器模式,以避免大量儲存。
如果 N 次重試嘗試失敗,請執行正常後援。 例如:
- 將數據儲存在本機快取中,並在服務可供使用時,稍後將寫入轉送至記憶體。
- 如果寫入動作位於交易範圍中,請補償交易。
診斷。 使用 記憶體計量。
從 Azure 儲存體 讀取數據失敗。
偵測。 用戶端會在讀取時收到錯誤。
復原:
- 重試作業,以從暫時性失敗中復原。 用戶端 SDK 中的重試原則會自動處理此動作。
- 針對RA-GRS 記憶體,如果從主要端點讀取失敗,請嘗試從次要端點讀取。 用戶端 SDK 可以自動處理此作業。 請參閱 Azure 儲存體 複寫。
- 如果 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 Analytics、Application Insights 或 New Relic 等服務來協助了解診斷記錄。
您可以在這裡取得範例。 它會針對下列例外狀況使用 Polly :
- 429 - 節流
- 408 - 逾時
- 401 - 未經授權
- 503 或 5xx - 服務無法使用
工作流程或分散式交易中的其中一個作業失敗。
偵測。 在 N 次重試嘗試之後,仍會失敗。
復原:
- 作為風險降低計劃,請實 作排程器代理程式監督員 模式來管理整個工作流程。
- 不要在逾時時重試。 此錯誤的成功率很低。
- 佇列工作,以便稍後重試。
診斷。 記錄所有作業(成功且失敗),包括補償動作。 使用相互關聯標識碼,讓您可以追蹤相同交易內的所有作業。
遠端服務的呼叫失敗。
偵測。 HTTP 錯誤碼。
復原:
- 在暫時性失敗時重試。
- 如果呼叫在 N 次嘗試之後失敗,請採取後援動作。 (應用程式特定。)
- 實作 斷路器模式 ,以避免串聯失敗。
診斷。 記錄所有遠端呼叫失敗。
下一步
請參閱 Azure 架構完善的架構中的復原和相依性 。 從一開始就,建置失敗復原到系統中應該是架構和設計階段的一部分,以避免發生失敗的風險。