自我修復的設計

將應用程式設計為在發生失敗時自我修復

在分散式系統中,可能會發生失敗。 硬體可能會故障。 網路可能會暫時性故障。 不過,即使是必須規劃中斷的整個服務、數據中心,甚至 Azure 區域也很少會遇到中斷。

因此,設計發生失敗時自我修復的應用程式。 這需要三管齊下的方法:

  • 偵測失敗。
  • 正常回應失敗。
  • 記錄和監視失敗以提供操作見解。

回應特定失敗類型的方式可能取決於應用程式的可用性需求。 例如,如果您需要高可用性,您可能會部署到區域中的多個可用性區域。 若要避免中斷,即使在整個 Azure 區域發生中斷的不太可能事件中,您也可以在區域性中斷期間自動故障轉移至次要區域。 不過,這會產生比單一區域部署更高的成本和可能較低的效能。

此外,不要只考慮大型事件,例如區域性中斷,這通常很少見。 您應該儘可能專注於處理本機、短期失敗,例如網路連線失敗或資料庫連線失敗。

建議

重試失敗的作業。 暫時性失敗可能會因為暫時失去網路連線、中斷的資料庫連線,或服務忙碌時逾時而發生。 在應用程式中建置重試邏輯以處理暫時性失敗。 針對許多 Azure 服務,用戶端 SDK 會實作自動重試。 如需詳細資訊,請參閱 暫時性錯誤處理重試模式

保護失敗的遠端服務(斷路器)。 在暫時性失敗之後重試是不錯的,但如果失敗持續發生,您最終可能會有太多呼叫端敲擊失敗的服務。 這可能會導致要求備份時發生串聯失敗。 當作業可能失敗時,請使用斷路器模式快速失敗(而不進行遠端呼叫)。

隔離重要資源 (Bulkhead) 。 某個子系統中的失敗有時可能會串聯。 如果失敗導致某些資源,例如線程或套接字,無法及時釋放,可能會導致資源耗盡,就會發生這種情況。 若要避免這種情況,請使用 Bulkhead 模式 將系統分割成隔離的群組,讓一個分割區中的失敗不會使整個系統關閉。

執行負載撫平。 應用程式可能會遇到流量突然暴增,而流量可能會使後端的服務不堪重負。 若要避免這種情況,請使用 佇列型負載撫平模式 來將工作專案排入佇列,以異步方式執行。 佇列可作為緩衝處理負載中的尖峰。

故障轉移。 如果無法連線到實例,請故障轉移至另一個實例。 對於無狀態的專案,例如網頁伺服器,請將數個實例放在負載平衡器或流量管理員後面。 對於儲存狀態的專案,例如資料庫,請使用複本並故障轉移。 視數據存放區及其復寫方式而定,應用程式可能必須處理最終一致性。

補償失敗的交易。 一般而言,請避免分散式交易,因為它們需要跨服務和資源的協調。 相反地,從較小的個別交易撰寫作業。 如果作業在中途失敗,請使用 補償交易 復原任何已完成的步驟。

檢查點長時間執行的交易。 如果長時間執行的作業失敗,檢查點可以提供復原功能。 當作業重新啟動時(例如,它是由另一個 VM 挑選的),可以從最後一個檢查點繼續。 請考慮實作機制,以定期記錄工作的狀態資訊,並將此狀態儲存在執行工作之進程的任何實例可以存取的持久記憶體中。 如此一來,如果進程已關閉,則會使用另一個實例,從最後一個檢查點繼續執行的工作。 有連結庫提供這項功能,例如 NServiceBusMassTransit。 它們會透明地保存狀態,其中間隔會與 Azure 服務匯流排 中佇列中的訊息處理一致。

正常降級。 有時候您無法解決問題,但可以提供仍然有用的縮減功能。 請考慮顯示書籍目錄的應用程式。 如果應用程式無法擷取封面的縮圖影像,它可能會顯示佔位元影像。 整個子系統對於應用程式而言可能不是關鍵。 例如,在電子商務網站上,顯示產品建議可能小於處理訂單。

節流用戶端。 有時候,少數使用者會建立過多的負載,這可以減少其他使用者的應用程式可用性。 在此情況下,請對客戶端進行一段時間的節流。 請參閱節流模式

封鎖不良動作專案。 只是因為您節流用戶端,這並不表示用戶端惡意運作。 這表示客戶端已超過其服務配額。 但是,如果客戶端持續超過其配額或其他行為不良,您可能會封鎖它們。 定義頻外程式,讓使用者要求解除封鎖。

使用領導者選舉。 當您需要協調工作時,請使用 領導者選舉 來選取協調器。 如此一來,協調器就不是單一失敗點。 如果協調器失敗,則會選取新的協調器。 不要從頭開始實作領導者選舉演算法,而是考慮現成的解決方案,例如 Zookeeper。

使用錯誤插入進行測試。 成功路徑經常經過很好的測試,但不是失敗路徑。 在執行失敗路徑之前,系統可能會在生產環境中執行很長一段時間。 使用錯誤插入,藉由觸發實際失敗或模擬失敗,測試系統對失敗的復原能力。

接受混亂工程。 混亂工程藉由隨機將失敗或異常狀況插入生產實例來擴充錯誤插入的概念。

請考慮使用可用性區域。 許多 Azure 區域都提供 可用性區域,這些區域是區域內隔離的數據中心集合。 某些 Azure 服務可以跨區域部署,以確保它們位於特定區域中,並可協助降低相同工作負載中元件之間通訊的延遲。 或者,某些服務可以使用區域備援來部署,這表示 Azure 會自動跨區域複寫資源以達到高可用性。 請考慮哪一種方法為您的解決方案提供最佳取捨。 若要深入瞭解如何設計解決方案以使用可用性區域和區域,請參閱使用可用性區域和區域的 建議。

如需讓應用程式自我修復的結構化方法,請參閱 設計 Azure 的可靠應用程式。