天天看點

自我修複型設計-常用的架構設計原則

設計應用程式應考慮系統在故障發生時能夠進行自我修複

在分布式系統架構設計中,應用可能會發生故障、硬體可能發生故障、 網絡也有可能發生暫時性故障。 極少數情況下,整個服務或區域可能會遇到中斷,但這些故障必須在計劃之内。

是以,我們設計的應用程式在故障發生時應當可進行自我修複。 要做到這點我們需要從以下三個方面入手:

  • 檢測故障。
  • 從容應對故障。
  • 記錄和監視故障,擷取操作見解。

如何應對特定類型的故障可能取決于應用程式的可用性需求。 例如,如果需要非常高的可用性,則可能在區域中斷期間自動故障轉移到次要區域。 然而,這将使成本高于單區域部署。

此外,不要隻考慮像區域中斷這類大事件,因為這種情況通常鮮有發生。 應該盡可能将注意力集中在處理本地短期的故障上,例如網絡連接配接故障或資料庫連接配接失敗等。

建議

一、重試失敗的操作

發生暫時性故障的原因可能有:短暫的網絡連接配接中斷、删除了資料庫連接配接或服務因繁忙而逾時。 在應用程式中建構重試邏輯來處理暫時性故障。 對于做好幂等操作的服務,用戶端 SDK 可實施自動重試。 有關詳細資訊,請參閱“暫時性故障處理和重試模式”。

二、保護故障遠端服務(斷路器)

在暫時性故障後最好進行重試,但如果故障仍然存在,最終可能會有非常多的調用方聯接故障服務。 但大并發量情況下對于所有失敗的請求都進行了重試的話,這可能導緻級聯故障。 而使用斷路器模式 ,無需在操作發生故障時重複無效的遠端調用就能快速解決這個問題,并且有效保障問題服務。 

三、隔離關鍵資源

子系統中的故障有時會發生級聯。 如果某個故障導緻某些資源(例如線程或套接字)無法及時釋放,導緻資源耗盡,則可能會發生這種連鎖反應。 為了避免此問題,請将系統分區為獨立的組,使一個分區中的故障不會導緻整個系統癱瘓。

四、負載分級

應用程式可能會遇到突發流量高峰,導緻後端上的服務癱瘓。 為了避免此問題,請使用基于隊列的負載調節模式使工作項排隊進行異步運作。 隊列充當可平緩負載高峰的緩沖區。

五、故障轉移

如果無法通路某個執行個體,請故障轉移到另一個執行個體。 對于 Web 伺服器之類的無狀态對象,請在負載均衡器或流量管理器後放置一些執行個體。 對于資料庫之類的存儲狀态的對象,請使用副本和故障轉移。 根據資料存儲和複制方式,可能需要應用程式處理最終的一緻性。

六、補償失敗的事務

一般情況下,需避免分布式事務,因為它們需要協調服務和資源。 相反地應該用較小的單個事務組成操作。 如果在中途操作失敗,請使用補償事務撤銷已完成的所有步驟。

七、使用版本或檢查點功能

如果長時間運作的操作失敗,檢查點可以提供複原能力。 當操作重新啟動時它可以從上一個檢查點恢複。

八、正常降級

 有時某個問題無法解決,但可以提供仍然有用的縮減版功能。 假設某個應用程式要顯示商品詳情。 如果該應用程式無法檢索商品的縮略圖圖像,它可能顯示占位符圖像。 整個子系統可能對應用程式不重要。 例如,在電子商務網站,顯示産品建議可能沒有處理訂單重要。

九、限制用戶端

有時少量的使用者會産生過多的負載,降低了應用程式對其他使用者的可用性。 在這種情況下,可以在一段時間内限制用戶端。 請參閱“限制模式”。

十、阻止錯誤執行元件

僅僅限制用戶端并不意味着用戶端的行為是惡意的。 它隻意味着用戶端超出其服務配額。 但如果用戶端持續超出其配額或在其他方面具有不良行為,則可能需要進行阻止。在這種情況下我們還可以定義一個異常的例外程序,供使用者請求解除阻止。

十一、使用協調器選拔或推舉方式

當需要協調任務時,請使用選拔方式來選擇協調器。 這樣協調器不是單一故障點。 如果協調器失敗,則選擇一個新的協調器。 這種開源元件相當多,比如現成的解決方案 Zookeeper。

十二、使用故障注入進行測試

通常情況下正常的路徑會得到精心的測試,而異常的路徑卻不會。 系統在生産中長時間運作後,可能會産生各種異常路徑。 通過觸發實際故障或模拟故障,使用故障注入來測試系統對故障的複原能力。

十三、采用混沌工程

混沌工程通過将故障或異常情況随機注入到生産執行個體中,擴充了故障注入的概念。

繼續閱讀