天天看點

面向失敗的設計-Planning for failure

引言

面向失敗設計的核心理念在于以一個悲觀的心态出發,假設系統地任何元件都有可能在某個時刻都會發生和預計不吻合的情況,為這些不符合預期的情況(failure)做好準備。然而,這個思想的前提在于,需要設計者,有足夠豐富的經驗,能夠把可能出現的狀況識别出來。

通常來說,"狀況”可以分為兩個級别的,一個是系統級别的狀況,例如,對容量的考慮,對資料備援的考慮等,對于這種問題,已經有了系統的研究領域,可以在系統開始設計的時候,就把這些可能的突發情況考慮進去,這種情況,不是我們這篇文章的讨論重點;還有一種狀況,這種狀況散落在各個環節,它們隻是一個“知識點”,或者”經驗教訓”,甚至隻是一個業務的預備計劃,它們并沒有規律。是以,我們需要一個系統,把這些狀況,系統地沉澱下來,在關鍵時候,能夠在複雜的情況中快速定位出問題,并且準确的執行應對的方案。

阿裡巴巴從2012年開始系統的沉澱這些”狀況”以及他們的應對方案,到今天已經第6個年頭了。在這6年中,沉澱出了一系列的有特色的理論以及成熟的預案平台系統。這套系統,覆寫了阿裡巴巴4000多個系統,支撐了電商交易的所有核心場景。阿裡巴巴也通過這套系統,從容的應對了6次電商領域規模最大,情況最複雜的雙十一。

這篇文章,将會介紹如何把結構化狀況以及應對方式,進而得以以系統地方式沉澱積累,成為可複用的預案;最後,文章會結合阿裡巴巴10年大促的實踐,給出實踐預案的原則性建議。

什麼是預案

一個系統在上線的過程中,可能會經過下面幾個步驟:

面向失敗的設計-Planning for failure

這些預案在足夠成熟的情況下,可以由系統自動探測并且執行;也有相當大的部分需要人工的幹涉。對于後者,我們可以遵循下面的原則來把這些預案盡可能全的搜集起來:每一個階段中,都可能産生預案。例如,采取微服務的政策,拆分應用,而服務之間有互相調用的關系,我們則必須為互相依賴的微服務不穩定或者不可用的做出預案,做出熔斷降級或者限制調用的準備;如果我們在設計的時候考慮到了單點問題,我們就必須為在緊急的情況下切換主備做好準備;同理,如果上線前,這個服務準備了機器部署,那麼我們就必須為真實流量高于服務容量做好預案。

  • “有前提條件,有預案”。舉一個例子,有一個系統,它能夠順利工作的前提是,它的處理能力在每秒1000個請求。當請求超過1000個之後,這個系統就會堆積任務,無法處理。這個相當于我們程式中的”assert”語句,我們必須通過限流或者其它的手段,來保證這個系統真正處理的請求,不會超過1000個。
  • “需要人工幹涉的操作環節,就需要準備預案“。從曆史資料來看,不少的系統不可用是由于人執行變更的時候造成的。如果這個人操作的環節,可以由系統自動執行,這是最理想的情況;即使無法被系統執行,如果有一個固定的操作流程,可以確定操作的正确性,也能夠大大的減低問題的産生。
  • “故障預案“。故障的複盤,總結出來的經驗操作,也是預案的重要來源。
  • “業務預案”。預案還有一種重要的來源,是和業務強相關的線上變更。舉個例子,在雙十一零點的時候,為了確定系統的穩定性,需要把推薦降級掉。這個業務變更,就是一種預案。

預案的标準

一個完整的預案,應該包含下面幾個要素:對解決的問題的描述;執行預案的條件;執行的動作;校驗的方式;以及把各個涉及角色串聯起來的工作流。

一個成熟的預案,具備下面幾個特征:

清晰的判定條件

一個預案,能夠沉澱到系統之中,要滿足充分的條件。即,通過特定的表征,可以确定,再這個情況下,可以執行某個行為。兩者是一個充分條件的關系。例如,僅僅憑”系統響應時間變慢”這個現象,我們不能做出把資料庫切成冷備的決策,因為兩者沒有明确的指定關系;而“當上海的使用者交易成功率下跌50%,其它地區的使用者交易成功率無明顯的波動”的表征的時候,我們可以做出把上海的買家的流量切到杭州區的決策。再比如,業務決定,“晚上20:00把頁面的banner換為紅色”,那麼到了晚上8點,我們就可以執行這個把頁面banner變紅的方案。

當條件足夠成熟的時候,我們可以把這個預案沉澱到系統之中去,由系統判定,目前滿足這個條件,進而自動執行對應的方案。如果還不夠成熟,可以加入人工的判斷。這種情況,往往需要有對應準确的監控,以及經驗的門檻值。随着算法的不斷發展,這些預案的比例也會占得越來越多。

一緻的執行

由于預案本身就有應急的特性。它的執行必須是高效,準确。目前大部分的系統是分布式的,這更增加了它的難度。例如,在某個場景下,需要打開業務開關,這個業務開關是通過REST服務,在各個應用執行個體上執行。我們需要保證這個開關要快速的執行,并且每台機器上的結果都要一緻,不能存在不确定性,例如,發生部分機器的開關打開成功,部分機器的開關不成功的情況。

可量化的校驗方式

當預案執行完畢之後,要能夠快速的得知執行的情況。預案的執行校驗,一般分為兩層,一層是系統層面的執行效果,通常表現為系統行為,例如,恢複供電,系統的開關打開等;第二層是業務效果,一般表現在業務含義上,例如,系統地某個業務開關打開後,業務是否走了對應的邏輯,表現出了不同的業務效果等。這就對應了兩種校驗。前者的校驗可以通過系統校驗,後者則需要業務方的參與。

隔離的工作流

線上上,一個預案從決策到執行,往往是涉及到多個環節,多個角色的。一個好的平台,應該能做到各個角色環節盡量隔離,做到每個角色隻需要關注自己需要關注的情況,明确的知道自己在什麼情況下需要做什麼。這個就需要系統清晰的定義工作流,把資訊做有效的隔離,如下圖所示:

面向失敗的設計-Planning for failure

通過隔離工作流,同一個預案的執行過程中,每個角色都隻需要關注自己的行為,而不需要受到别人的幹擾。這樣,才能夠在突發的情況下,效率最高的處理自己的事情。

預案的生命周期

面向失敗的設計-Planning for failure

預案的也有它的生命周期,一般來說,我們可以認為預案由梳理預案,開發預案,測試,上線,演練,最後下線的幾個階段。

梳理預案:我們的系統沒增加一個功能,可能帶來的風險點,都需要被定位出來。這些風險點,我們通過評估它的影響,來為之準備應對的方案。

開發預案:當一個風險點被梳理出來,我們需要準備預案的應對方案。這個應對方案有可能是業務中的一個開關,也有可能是執行腳本,甚至是文字描述的執行步驟。無論這些應對方式是否可以系統化的執行,都要将他們中性且客觀的沉澱下來。

測試:開發完畢之後,需要測試這個預案的執行效果是否如預期所示。這個測試,分為兩種級别的測試,一個是系統層面的測試,例如業務的開關是否推送成功等;一個是業務含義的測試,例如這個開關執行之後,系統的表現行為是否如預期所示。

上線:測試完畢之後,就可以再線上運作了。

演練:這個是非常容易遺漏的一環。預案的正确性需要長期的維護,它可能再線上很長的時間并不會被執行到,但是我們必須要保證它是一個有效的預案。是以我們需要線上上進行定時的演練,保證預案的有效性。

下線: 随着業務,結構的發展,預案也會失效。

預案的成熟度模型

我們可以把預案的成熟度分為幾個等級:

面向失敗的設計-Planning for failure

預案在阿裡巴巴的最佳實踐

阿裡巴巴在這幾年中,也沉澱了一套預案的最佳實踐,在不同的階段,有不同的重點。

面向失敗的設計-Planning for failure

在大促,活動開展之前,對已知風險點,必須有對應的預案。阿裡巴巴針對重要的業務鍊路,組織涉及的每個系統進行橫向梳理。對于梳理出來的可能的風險點,都必須有對應的預案産出;對于曾經發生過的故障,也必須有對應的預案沉澱下來。最後,這些預案會集中在預案平台中統一管理,這些預案,可以根據業務,場景,都友善的定位到。

在準備大促的時候,預案必須經過線上的校驗。雖然預案是有觸發條件的,但是我們也必須保證預案的正确性。因為預案本來就是在緊急情況下執行的一個措施,它的不确定性必須控制在最小的範圍之内。

定期演練預案。我們不能期待一個未經驗證的預案,在緊急問題發生的時候,就能夠使用。例如,在系統設計的時候,考慮到了對資料庫的冷備庫切換的預案。當系統落地之後,我們就驗證了這個預案的正确性。但是随着業務的發展,我們對資料庫增加了表單,我們如何確定預案能夠正确地同步這些變更了?是以,我們也必須對這些預案進行持續的驗證。最後,預案必須要定期的演練。這個演練,不僅僅包含預案的正确性,還包括對緊急情況的預演。

預案的報表,也是非常重要的。因為這是一個直接的量化标準。可以直接看到預案的演練情況。

文章來源:AlibabaTechQA

開發者社群整理