阿里妹導讀:18年前,200家企業因爲在事故中信息系統遭到嚴重破壞而永遠地關閉了。這樣的事故引起了後人深思,對於工程師而言,不只要求設計的系統足夠強壯,還須要具有考慮失敗的能力,當失敗場景悉數被考慮周全、而且結合充分的演練,一切會不會不同?咱們熟知面向對象設計和麪向程序設計,阿里巴巴資深技術專家遊驥洞悉行業現狀,拋出了一個新模式——面向失敗設計。今天,聽他娓娓道來,如何在一開始的系統設計階段就考慮到各類失敗場景,把面向失敗當成是系統設計的一部分,準備好從失敗中恢復的策略。
一個優秀的架構師一般都是一個悲觀主義者,除了設計好可以支撐業務持續發展的優雅架構,另外一個容易被忽略的重要能力在於充分考慮失敗場景。若是對失敗場景考慮不夠充分,輕則出現業務不可用,影響用戶體驗和企業聲譽;重則致使數據永久丟失、業務再無恢復可能。程序員
2001 年 9 月 11 日,美國世貿中心雙子大廈遭受了誰也沒法預料的恐怖打擊,災難發生前約有 350 家企業在世貿大廈中工做,事故發生一年後,重返世貿大廈的企業變成了 150 家,有200 家企業因爲重要信息系統的破壞,關鍵數據的丟失而永遠關閉、消失了,其中的一家公司聲稱本身要恢復到災難前的狀態須要 50 年的時間。數據庫
「Everything fails, all the time」,不管是在傳統軟件時代仍是在互聯網、雲時代,系統終究會在某個時間點失敗,面向失敗的設計理念數十年來並無多大的變化,不一樣的是在分佈式、雲架構的互聯網時代:失敗將由小几率偶發事件變成常態,同時應對和處理失敗的具體實現方式也截然不同。緩存
單個技術點在絕大部分時間都能按照設想正常工做,可是當規模和複雜度到達必定程度,失敗其實無所不在。當你的業務場景從服務企業內部的幾百號員工變成面向上億的外部用戶,你不肯定你的用戶羣會有些什麼樣的角色,也不知道他們會在你的系統平臺上創造出什麼樣的業務行爲;當你的技術框架從單機、一體機演進到分佈式的多層、多組件架構,本來5個之內的技術組件可能變成了今天的500個,而且爲了用較低的成本保持服務能力的擴展能力,你可能放棄了穩定性更好但也昂貴的商業技術、轉而用開源自建來替代。安全
互聯網業務快速發展不只直接帶來了流量、安全等不肯定性,同時促使了技術架構的快速演進,使架構變得愈來愈複雜,這些因素都將致使失敗發生的機率大幅提高。當人類的工做、生活愈來愈依賴互聯網,一旦出現失敗,形成的影響和損失將是空前巨大的。在遠古時代,人類沒有自來水也沒有電,一切都很好;今天若是停電停水一段時間,相信不少人都會沒法適應,而互聯網正在逐步演變成跟水和電同樣的基礎設施。失敗的緣由多種多樣,抽象來看能夠分爲如下幾類:架構
硬件問題框架
首先,硬件是有生命週期的,它必定會老化,而且你不知道它會在何時壞;其次,硬件是一個實體,它存在於客觀環境當中,它的狀態會受外部環境干擾,好比火災、地震等外力因素均可能致使硬件損壞;最後,全部硬件都會存在殘次品,你極可能就是那個不幸者。一般狀況下單個硬件出問題的機率不高,可是當有幾十萬的硬件設備,硬件的失敗問題天天都會發生。運維
軟件bug分佈式
即使是最優秀程序員寫出來的程序,通過最優秀測試同窗的嚴格測試後的代碼,上線依然沒法作到徹底沒有bug。互聯網業務迭代每每講究一個「快」字,以往幾個月或者幾年升級一次的軟件程序,如今一週就須要升級一次或者屢次,這大幅提高了軟件出錯的可能性。測試
配置變動錯誤spa
系統運行態的平常運維過程中,不免會由於疏忽或者考慮不周全致使災難。當上萬名技術同窗跟上百個變動系統作笛卡爾積,哪怕是6個9的可靠性,依舊沒法作到萬無一失。全局的流量入口、權限與安全驗證體系、統一網關與接口平臺等技術環節是可能促發全站不可用的重要風險點,對於影響面大的配置的變動須要尤其謹慎。
系統惡化
本來工做得很好的程序隨着時間的推移可能有一天再也不正常工做,舉幾個常見的例子:自增變量運行了很長一段時間後出現越界、緩存隨着數據量的逐漸變大而出現空間不足、數據庫鏈接池隨着機器的擴容而不夠用等等。千萬不要認爲運行良好的系統是不會出問題的,它的代碼裏面可能藏了定時炸彈,只是你不知道會在什麼時間點爆炸。
超預期流量
某一天你的系統可能忽然會承受遠超過預期的每秒請求數,特別是在「中國特點」的互聯網場景之下,你很難精確預估系統各個時間點的業務訪問量。
外部攻擊
你須要考慮各類攻擊行爲,包含流量攻擊和安全攻擊。你的系統可能隨時會面臨着DDOS和CC類攻擊,你傳輸的數據可能會被盜取或者篡改。
依賴庫問題
你的系統極可能會用大量的二方庫或者三方庫,它們對你來講是黑盒子,你不瞭解它們存在哪些風險,而且你沒法掌控。這些庫可能會存在漏洞、可能會有bug,可能會大量消耗你的系統資源,總之不要太信任它們。
依賴服務問題
你依賴的服務也必定不會100%可用,它們可能會超時,可能會失敗。當依賴服務超時的時候,若是你沒有很好地處理,可能會致使你本身的系統沒法工做,在分佈式場景下,這種失敗狀態會持續輻射,最終致使大面積的不可用。
做爲一個悲觀主義者,你須要在一開始的系統設計階段就考慮到以上各類失敗場景,把面向失敗當成系統設計的一部分,而且準備好從失敗中恢復的策略,這有助於更好地提高整個系統的可用性。只有你意識到事情會隨着時間的推移而失敗,並將這種思想融入到體系結構中,那麼在失敗發生的時候你才能徹底不受影響或者將失敗損失降到最低。面向失敗的設計理念數十年來並無多大的變化,一些好的經典原則在今天依舊被普遍運用。
冗餘設計避免單點故障
硬件和軟件都不可靠,環境和人都存在極大的不肯定性,雖然沒法避免失敗場景的發生,可是能夠經過冗餘設計來規避局部失敗對系統的影響。冗餘設計避免單點故障這一策略在互聯網技術架構中到處可見,好比重要的服務一般都會部署多個、數據庫的主備結構、服務調用的重試機制、存儲的多副本等概念都屬於這一範疇。
面向失敗的宏觀多活架構
除了局部失敗場景,你的系統可能還面臨着大範圍的失敗場景。大範圍的緣由有兩個:天災,好比火災、地震、颱風、雷電等大的天然災害可能致使大面積的基礎設備被毀壞;人禍:人的失誤或者刻意破壞行爲有時候也會釀成大禍,如操做錯誤、破壞、植入有害代碼和恐怖襲擊。「面向失敗的宏觀多活架構」從宏觀架構的高可用層面來解決系統的總體可用性問題,隨着技術的演進,冷備、熱備、兩地三中心、異地多活等應對大範圍失敗場景的技術體系這些年頻頻被提起。
服務能力與依賴調用自我保護
如何來衡量一個軟件系統的設計是否優良?一條很重要的衡量標準——在任何狀況之下你的軟件系統都應該工做在當前環境的最優狀態。每一個人都知道機翼是飛機的重要部件,一旦機翼出現問題,飛機極可能就會墜落。然而在二戰當中,許多戰鬥機即使機翼千瘡百孔了,依然保持着最佳戰鬥能力;甚至還有更誇張的狀況:1983年的一次戰鬥機演習當中,一架飛機因爲事故損失了一個機翼,這架缺乏一個機翼的飛機依然保持了飛行能力、最終完成安全着陸。
軟件系統由兩部分構成:系統自身的代碼和依賴的庫以及服務。「服務能力與依賴調用自我保護」須要從這兩塊分別切入構建系統在任意狀況都始終工做在最佳狀態的能力。服務限流、系統負載保護、給依賴的服務設置超時或者資源限制等都是相應的應對策略。
爲一切不可預料的狀況備好預案
可以抵抗失敗和從失敗中快速恢復是面向失敗設計的核心思想,然而即使已經作了萬全的設計,也並不是全部的失敗場景都是系統可以自動抵禦的。你須要考慮到全部的失敗場景,並準備好相應的應對預案。爲一切不可預料的狀況備好預案才能在失敗場景真正發生時作到有條不紊。作好預案須要對失敗場景有全面的考慮:會發生哪些失敗?失敗會帶來什麼問題?應對策略是什麼?預期的恢復時間多久?恢復後的影響面有多大?須要通知到哪些角色?等這一系列的因子構成了一個完整的預案體系。
自動化運維管控
大量的系統故障是由於人的失誤形成的,即使讓一個優秀的運維工程師進行一萬次一樣的運維操做也不免不出錯。惟一的解決辦法即是在運維過程中儘量下降人爲操做的比重。系統化、白屏化是第一個階段——將人爲的操做步驟固化成系統程序,避免操做失誤;自動化以及智能化是第二個階段——將正確的決策過程也固化成智能程序,避免決策失誤。同時全部的運維動做都須要遵循灰度原則,作到可灰度、可監測、可回滾,即使出現了失誤也能控制好爆炸半徑,而且作到快速恢復。
精細化的監控體系
面向失敗設計不只要求你的系統足夠健壯,同時要求你可以在第一時間感知到失敗的發生。不管是自動化的系統恢復,仍是人爲介入,若是你壓根都不知道是哪裏出問題了,一切都將一籌莫展。精細化的監控體系一方面可以在出現問題的時候以最快的速度將最準確的信息傳遞到人或者運維繫統,同時它還可以展示趨勢、進行提早預警。AI技術的結合使得監控領域在近幾年獲得了新的發展驅動力:智能監控報警、根因定位、智能預測、智能決策等能力都是學術界和工程界很是熱衷的課題。
故障與攻防演練錘鍊容災應急能力
最後,即使以上工做都作好了,你也不能高枕無憂去等待失敗到來。你的設計、系統、流程、技術人員等須要經過不斷演練,來保障能力和進化升級。對於代價很是巨大的事件,作好前期的充分演練是很是有必要的,好比軍事演練、消防演練等都屬於這一範疇。而系統不可用的代價對於企業來說極可能是沒法承受的,所以須要在平時作好充分的演練:經過故障與攻防演練錘鍊容災應急能力,對面向失敗的設計作好充分驗證。只有當全部的失敗場景都被提早演練過,當失敗真正來臨時才能作到成竹在胸。
本文來自雲棲社區合做夥伴「阿里技術」,如需轉載請聯繫原做者。