Design for failure常見的12種設計思想
本文轉載自微信公眾號「架構精進之路」,作者張張 。轉載本文請聯系架構精進之路公眾號。
hello,大家好,我是張張,「架構精進之路」公號作者。
通常情況下,我們的一個請求會經過三個服務來處理。
請求從客戶端發出,到達Proxy Layer(執行一些公共的邏輯,如邏輯、流控、審計等),完成后,發往App Layer(執行具體業務邏輯),執行完畢后,發向Data Laye(進行數據持久化)。
事情看起來很簡單,然而,在一個分布式系統中:出錯是常態。
因此,我們需要:Design For Failure。即當你的系統將錯誤當作正常流時,系統便已經對錯誤免疫了。
在此,跟大家介紹常見的12種設計思想。
1、防御性設計(Defensive Design)
所謂的防御性設計實際上就是“防呆”,英文叫Idiot Proofing。說白了就是用戶有時候會不自覺的做一些蠢事,我們在設計的時候要盡量考慮到一些不規范的交互行為,如果你的用戶是一只猴子,你要寫包單保證系統不被玩壞。
例如,在Android開發中使用到的Monkey Test就是用于這樣的目的。
2、邊界情況(Edge Case)
這個設計思想在測試領域比較常見,就是我們在設計我們的設計案例的時候有沒有充分考慮在邊界情況下的系統行為。
比較常見的例如,閏年情況、跨日情況等邊界。
3、防誤措施(Mistake Proofing)
怎么保證不會發生錯誤。例如在人機交互環節,能不能進行輸入校驗?
4、解耦(Decoupling)
設計的時候,哪怕是最基礎的代碼也應該符合開閉原則。
Spring的IOC就是為了把對象創建及維護從原來的由引用類負責這種強耦合模式轉成通過spring容器負責。且解耦一般的做法是通過把內部邏輯封裝起來,暴露對外統一API接口,調用方不需要了解被調用方的內部邏輯實現,只需要知道提供什么功能即可。
再引申一下,解耦的作用就在于復用,把所有的高內聚功能獨立成一個個模塊,然后就可以像樂高積木一樣根據調用方的實際需求進行組裝。
5、冗余(Redundancy)
所謂的冗余指的通過重復配置關鍵組件或部件,保證在關鍵組件失效的情況下還有備份組件運作以便保證系統可以繼續提供服務。生活中的例子請參與飛機的雙引擎設計。
主從模式就是冗余的體現。在正常情況下,主實例負責提供全部的服務,從實例在主實例整體或部分不可用的情況下,完全替代主實例整體或局部而對外提供服務。
6、重試(Retry)
重試是在分布式系統下處理瞬態故障的一個基本手段,簡單有效(當然重試的前提是要求冪等)。但是重試也是可以很危險的,它能夠引起把一個局部小時間迅速升級為一個系統重大故障,嚴重者導致系統假死。
舉個簡單例子:如果我們的鏈路類似上圖,這里會發生什么問題?
在極端情況下,重試次數達到5*5*5*5=625次。
當鏈路中的其中一個服務故障率異常的時候,那重試風暴便開啟了,因為重試為服務器帶來額外的開銷和線程的占用,然后其他新來的請求又形成排隊,這樣的話就形成了類似的DDos惡性事件。
7、冷備(Cold Standby)
冷備實際上也是冗余設計的其中一種體現,只是它會更側重于“冷”,意思是當系統發生宕機時,這個系統是需要手動啟動用于替換下線的主實例,它是跟熱備是不一樣,熱備更多體現在自動切換。
8、熔斷(Derating)
熔斷本質上就是一種防御性設計或者策略。假設一個微服務體系下的系統,其中A服務調用B服務。系統的QPS是千級別,當時如果B服務掛掉的話A的線程絕對在短時間內占滿耗盡而導致假死,從而形成大量A請求積壓而導致情況惡化,最終形成雪崩。
9、容錯(Error Tolerance)
狹義的容錯泛指人機交互界面的時候需要對用戶輸入進行輸入校驗,保證數據準確性。
廣義的容錯應該是兩個具有明確邊界的事物(如服務間,系統間)交互時候針對可能發生的一切主客觀異常情況的防御性手段。常見的容錯機制有failsafe、failback、failover、failfast。
- failfast 更多指的是快速失敗,避免線程積壓導致系統滾雪球式崩潰。
- failover 指的是失效轉移。
- failsafe 指的是失效安全。
- failback 指的是失效自動恢復,將故障實例切換到備實例。
10、失效安全(Fail safe)
所謂的失效安全,就是指在特定失效的情況下,一個系統或者服務也不會對業務造成損害。
例如:我們使用token進行安全登錄也是一種失效安全的體現,如果token失效了(如時間過期),用戶是無法登錄的,因為正常登錄需要token有一種約束因素,這種因素就是時間。如果時間過了,代表這種約束因素不存在或者不再有效了,登錄功能就不能正常工作了。
11、優雅降級(Graceful Degradation)
服務降級跟熔斷還是挺像的,只是降級來得更加溫和和優雅一點。熔斷是直接斷掉防止異常進一步擴大而導致雪崩,但是我們的終極目標是提供盡可能多的服務,這個就是優雅降級的理念。在一些異常情況或者秒殺場景下,為了保證核心服務(如商品下單、支付)的正常可用,會放棄掉一些非核心服務(如歷史賬單查詢),這就是所謂的服務降級。
在微服務框架中,一般會使用Hystrix的@HystrixCommand或Feign的@FeignClient對服務進行聲明,然后為每個服務配置相應的fallback類,最終結合起來進行服務降級。
12、耐用性(Durability)
這里我理解的是系統或數據的耐受性。
例如數據,為什么我們一定要持久化到數據庫,因為就是要借助數據庫硬件各種維度的耐受性。
補充
作為一名designer或者developer,應該要對墨菲定律心存敬畏。
另外,需要額外補充一點的就是:監控(Monitoring)。
我們的系統有哪幾個緯度的監控,估計最多就是常規的硬件狀態監控。當然這里的監控我理解除了技術指標監控,還更應該有業務指標監控,否則我們都在裸泳,等海水退下去后就一覽無遺。
監控實際上是為了更好的主動防御,一套完善的告警監控系統,能夠快速通知開發與運維,開發側能夠完成緊急修復并能夠協同運維進行快速部署。