本文從業務角度介紹微信支付實踐混沌工程落地的思考,透過多分區的架構來控制最小爆炸半徑,在高價值的基礎元件和微信支付核心業務場景上探索,並基於高可用原則、歷史故障分析推導故障原子的開發,是一篇全面的混沌工程建設實踐。
作者 | 劉斌 責編 | 夏萌
出品 | 騰訊雲開發者
業務場景:微信支付服務於千萬商戶和億級使用者,可用性要求高於 5 個 9;
落地矛盾:註入故障需貼近實際故障環境,對現網業務無影響/弱影響;
實踐難點:如何控制最小半徑,如何高效、全面挖掘風險;
業務收益:發現多處元件和業務風險,從0到1建設起混沌工程系統;
未來展望:更豐富的故障原子;自動化;支持多類半徑實驗。
為什麽要做混沌工程
1.1 目標起點
微信支付是國家關鍵資訊基礎設施,服務千萬商戶和億級使用者,可用性要求高於5個9。
1.2 分析:影響可用性的主要因素及應對
為了分析影響可用性的因素,我們對2018 ~ 2021近幾年微信支付的故障復盤數據分類,發現軟硬體異常導致的故障占比較高(如下圖的基礎設施、元件、上下遊部份)。
各類引發故障的因素,微信支付采取了相應的應對措施,如
功能/程式缺陷:單元測試,整合測試,UAT 測試,流量回放;
容量不足:常態化壓測,自動彈性伸縮;
人為破壞(人因):去登陸 IDC,變更稽核,許可權控制,模組認證;
但對於軟硬體故障,雖然基礎元件會涉及一些容錯處理,但設計是否全面、開發是否完全實作、真實場景是否有效,沒有統一的工具和驗收標準,並推動解決。
如何檢驗系統具備應對軟硬體異常的容災能力,我們調研了公司和業界的方法,其中演習和混沌工程最為常見和有效。它們都強調線上上實施,目的都是提高系統的可靠性和彈性,但方法和側重點有所不同(區別兩者概念和思路,對實際落地影響較大)。
1.2.1 演習
演習通常是有明確的執行計劃和預期,要求註入故障的影響已知且明確。
更關註人的反應和應急響應計劃,還包括非系統因素都在考量範圍。比如驗證某個系統失效後的,人為幹預流程、機制是否順暢等。
1.2.2 混沌工程
(公司和業界有非常多的關於混沌工程的概念介紹,如不了解可先自行搜尋,不再贅述。)
混沌工程在目標上更強調 發現未知的風險 ,更關註系統的彈性,不涉及系統外的因素。其中 Netflix 提出的混沌工程五大原則是業界落地實踐的普遍共識:
建立穩定狀態的假設;
用多樣的現實世界事件做驗證;
在生產環境中進行實驗;
自動化實驗以持續執行;
控制最小化爆炸半徑。
其中多樣化的事件和控制爆炸半徑的方法,相對演習有明顯差異。也正是控制了爆炸半徑,混沌工程裏註入故障的強度、復雜度遠高於演習能力,能更全面、真實的模擬現網故障,以達到」發現未知風險「的目的。
此前,演習是微信支付容災驗證的重要手段,我們發現演習因為沒有系統的爆炸半徑控制方法,所以從工具開發、監控穩態辨識、事件的多樣性、自動化等方面,演習都需要較多的客製開發和人工即時觀察,人力投入成本較高。
因此,引入混沌工程體系,透過有效的控制爆炸半徑,進而更大振幅的註入異常並適當建設自動化能力,來辨識系統薄弱點並推動持續治理來提高可用性,是當前值得探索的方向。
1.3 可行性
落地混沌工程有兩大矛盾點:
故障有效,註入的故障貼近實際發生故障環境;
業務安全,註入故障對現網業務無影響或者影響較低。
為了貼近真實環境,註入故障離真實環境越近越有效,但這又勢必影響業務可用性。且微信支付對可用性要求高,不接受不可預知的風險。如果沒有解決業務安全問題,就引入混沌工程「探索未知風險」的期望就較難落地。
在2021年,微信商業支付做了多分區改造,將業務流量路由到不同分區,分區間相互獨立、互不影響,分區間環境一致性透過 DevOps 部署保證。在分區隔離的 IDC 環境裏註入故障,調配可控的流量,既能貼近生產環境,又能確保故障收斂、控制爆炸半徑。這樣,微信商戶支付落地混沌工程已具備條件和可行性。
如何落地
從業界落地混沌工程經驗來看,基本是圍繞 Netflix 提出的5大原則展開。
建立穩定狀態的假設,即從使用者角度衡量業務健康度,一般業務都有現成的業務監控,大多情況無需額外開發。
用多樣的現實世界事件做驗證 即 豐富註入故障的型別,自動化實驗以持續執行 即 降低人工參與成本,兩者都需要額外開發,但先開發哪些、做到什麽程度,可結合業務目標,更多的是開發人力成本和可挖掘到的風險收益之間 ROI 考量。
在生產環境中進行實驗和控制最小化爆炸半徑,是混沌工程的有效性和安全性的兩個關鍵問題。
因此,落地混沌工程的主要難點是:
安全、有效的實驗;
高效、全面的發掘風險。
2.1 安全、有效的實驗
不同的技術選型對應的有效性和安全性如下:
一般來說,有效性和安全性很難同時滿足,而且是此消彼長的關系,越是希望真實還原故障,就需要在有業務流量的真實環境中模擬故障,這又會影響業務安全;但若一味追求安全,不能對業務有任務影響,就無法還原故障發生的真實場景,又很難發現問題。可結合實驗目標,確定業務能接受最低限度的安全性,來選擇有效性最高的方案。
2.1.1 安全:不影響線上業務
控制爆炸半徑
爆炸半徑的方案選擇,在混沌工程實施的不同階段,也是可以調整的。對系統可用性的信心越足,越是可以貼近真實環境,因此前期可以在有效性低的環境中實驗,當實驗手段很難發現新問題且發現的問題都已解決時,可以考慮升級到有效性更高的方案。
對微信商業支付,如前文介紹在2021年已經進行了多分區改造,因此我們在多分區架構上,單獨規劃了分混沌分區路由和4個業務分區,部署的業務邏輯模組、儲存、元件等都與生產分區完全一致,前期放入仿真流量到混沌分區後註入故障,當對系統具備足夠的信心後,後期在生產分區註入故障。
由於多分區僅對核心業務做了改造,仍存在外部依賴服務,為了防止混沌實驗對外部依賴的影響,對不同場景的風險源做了相應處理:
特殊限制與審批
考慮」數據篡改「類的故障,可能會導致寫臟數據,尤其是篡改業務執行主體(如商戶 ID、使用者 ID)寫臟真實業務數據的風險,因此禁止」篡改執行主體「的故障。
考慮執行的實驗的風險,我們對這些場景加了審批:
「修改」類的故障加審批。避免寫臟異常影響真實環境,由leader二次評估確認。
非資源負責人執行審批。如對他人模組實驗(模組混部對母機實驗校常見),避免無法發現其它業務異常。
非工作時間實驗審批。避免實驗異常,幹預時間長。
2.1.2 有效:貼近真實環境
我們主要在隔離的混沌分區實驗,實驗環境與真實環境一致性越高,真實環境出現類似的問題機率就越大。
靜態:部署環境的一致性
部署環境一致性的主要維度如下:
我們將上述高一致性要求的地域、園區、容器、二進制、配置,做到 DevOps 部署工具中,上線模組、釋出變更時做到與投產環境一致。
動態:實驗流量的逼真度
實驗流量與線上接近的目的,一是還原機器/容器負載情況,二是還原業務執行的分支,兩者在某些復雜組合場景下,是否會觸發未知風險。我們從兩個維度來評價流量仿真程度:
基於這兩個指標,有兩個不同方向:
考慮前期建設成本和不確定性,我們選擇了人造流量方案。
2.2 高效、全面的發掘風險
從0到1建設混沌工程系統和業務落地,我們遇到了這兩類問題:
我們選擇從業務目標出發,優先看高價值的風險點,工具配合業務目標逐步豐富故障原子。根據不同階段的側重點,將計畫的實施路徑拆分兩個階段:
2.2.1 發掘高價值風險
前期,人力、工具有限的條件下,如何發掘高價值風險(高 ROI)?
較簡單的方法是:隨機註入。工具團隊可根據近幾年的故障型別,按照優先級開發出對應的故障原子,無差別的註入到目標模組。當前期自動註入、穩態分析不夠健全的情況下,仍需人工參與,這種方法有2個局限:
實施的業務團隊人力投入大:人工註入故障,人工觀察、分析業務監控,以及監控偏離時是否影響業務、是否會擴散風險、是否有其他潛在風險;
工具團隊不能做到有的放矢,不能將有效的人力投入到最有價值的原子開發上來。
為了快速找到高價值風險,進而提升大家參與的積極性,我們選了如下2個策略:
1、實驗物件從 高價值 往 低價值 覆蓋。根據這個思路,得到了優先實施的模組。1)公共元件:RPC 框架、佇列、儲存 、緩存,安全認證、日誌等;2)生命線業務:收付結退。
2、基於高可用原則拆解,得到工具待開發的原子需求和待註入的資源。
透過這些策略,我們快速的找到 HTTP 接入模組、事件中心、跨城元件等微信基礎元件的多個高風險的共性問題。
2.2.2 找全風險
後期,如何增強覆蓋面,發掘更多未知的黑天鵝風險?
上述方法,只能覆蓋到有限的故障域,而實際故障往往是由多個事件同時發生而觸發,因此後期加強單原子無差別的註入和組合故障的註入可以發現更多中長尾問題。
對於組合故障,如果也是無差別策略,那麽組合空間極大,就以微信支付委托代扣業務為例:
單故障註入:18模組 * 15個故障原子 = 270個,即單原子無差別的註入次數;
2個組合空間為 C2270 = 36315,任一組合空間為2270。
即使工具已經具備自動註入、自動分析的能力,實驗周期和消耗資源也將會很高,因此合理的剪枝很有必要,可采用基於相關性由強到弱的多故障組合,如:
模組內構成依賴關聯影響(包括三園區容災設計);
業務內模組間依賴關聯影響;
業務間依賴關聯影響;
基礎設施間依賴關聯影響;
潛在依賴關聯影響。
2.2.3 自動化
從實驗流程來看,除了「修復問題」,另外三個流程可以做到一定程度的自動化。
自動設計
一個實驗任務由4個部份組成:
業務資產:集群、模組、介面;集群是多個模組的總稱,如某個儲存集群包括接入模組、儲存模組、後設資料模組;
系統資源:業務資產執行所依賴的機器、容器、網路、CPU、磁盤、行程、檔、記憶體、共享記憶體等;
故障型別:針對每種系統資源的有多種故障,如機器包括機器重新開機、機器時間錯誤等,如網路包括慢、丟包、亂序等。
故障程度:除個別的像機器重新開機這類0-1型別故障,其它大多數涉及一定程度的故障,比如網路丟包30%,不同程度下的表現略有不同,一般將故障程度拆解成幾檔,如丟包有單機內10%、30%、50%、80%、100%,再組合多機情況。
一個實驗,首先圈出所包含的業務資產,再整理出其依賴的系統資源(除了磁盤、檔、共享記憶體這幾項,其它一般都包含),再展開系統資源的故障型別,最後確定故障程度,有兩種策略:
標記資產型別,如標記為某類儲存集群,則套用已設計過的實驗樣版庫生成實驗任務;
標記業務所適用的高可用原則,如單機/園區剔除能力、異常防禦、分區切換、旁路冗余設計等,裁剪掉全展開的無效程度值,如單機剔除原則只容忍下遊單機或單園區機器故障所以不生成多機故障,而做了旁路冗余設計的業務則容許旁路模組的所有機器故障所以生成單機故障的必要性就不大。
因此業務需要做的是:圈定資產範圍及依賴的系統資源,並標記資產型別或適用於哪些高可用原則,便可自動生成實驗任務。
自動執行
系統建設不是一蹴而就的,從手工執行到自動化我們經歷了三個階段:
手動執行單個故障,主要解決0-1的問題,主要精力放在故障原子建設上;
單次批次執行多個故障,采用 yaml 檔記錄編排方式,支持序列、並列排程。套用於業務首次實驗和定位問題。
定時執行/事件觸發執行,主要用於變更回歸和可用性巡檢場景,因為定時執行也依賴後續的「自動分析」,所以放在最後。
自動分析
上述自動執行減少了「點選」操作的工作量,實驗要」完全「自動化,還要結合自動分析,即自動判斷是否偏離穩態。一是當穩態偏離正常範圍及時停止,避免造成次生災害;二是只有做到自動分析,才能低成本的「定時執行」,否則每次自動執行後都依賴人工分析,不永續。
我們根據實驗的時間(實驗開始時間到實驗結束後一個周期),自動匹配與之相關的穩態告警:
業務:業務用例維度監控是否觸發告警。強優先級,觸發後停止實驗。
模組:上下遊呼叫關系是否出現告警。中優先級,觸發後不停止實驗,展示在實驗報告中。
IP/容器:機器和容器是否出現資源異常告警。中優先級,觸發後不停止實驗,展示在實驗報告中。
業務自訂監控,上述無法自動覆蓋的監控,由業務配置後自動收集。
2.2.4 風險處理
發現的風險的除了負責人處理外,方法:
個性問題:周知元件、業務負責人處理
共性問題,透過 SOA 治理、架構模式化、完善研發流程等手段來大規模消除,達成組織價值最大化。
對不同時期出現的問題采用不同的策略:
存量:采用了 SOA 治理平台推動修復(SOA 治理是微信支付風險和異常項治理的平台,提供了統一的異常接入、展示、周知、跟進管理的指標數據,在部門內形成了統一的風險治理共識,以快速治理、收斂風險。混沌工程將發現的風險接入 SOA 治理平台,快速治理大面積的共性風險)。
新增:透過 MR 流水線門禁和變更門禁堵住新增,需處理後才能透過。
成果
我們透過一套流程推進:設計實驗(建設原子) - 執行實驗 - 分析結果(挖掘問題) - 修復問題,在業務風險挖掘和工具建設上都取得了不錯的效果。
3.1 業務成果
2021年上線至今,線上0故障,執行實驗計劃60+個,實驗任務500+次,覆蓋業務、框架、元件多類場景,並行掘多處風險。
3.2 工具建設成果
微信支付從0到1建設了混沌工程系統(由業務連續性架構中心和支付運維組建設)。
已支持30+種故障原子,典型原子:
頁面支持拖拽式編排、串並列編排,並可配置定時啟動實驗用於常態化驗證風險。
透過關聯微信支付的模組呼叫異常告警、業務監控告警,辨識正在實驗的模組/IP 潛在異常,在實驗報告中展示出來,提高實驗後分析效率。
總結與展望
4.1 總結
本文從業務角度,介紹微信支付實踐混沌工程落地的思考,透過多分區的架構來控制最小爆炸半徑,首先在高價值的基礎元件和微信支付核心業務場景上探索,並基於高可用原則、歷史故障分析推導故障原子的開發。發現了多處共性風險,並推動修復和治理。
4.2 展望
4.2.1 更豐富的故障原子建設
有效性和安全性始終是一個權衡取舍的因素,如前文介紹,微信支付在獨立的混沌分區架構中實施,前期使用仿真流量,因此除篡改數據類的原子外,在控制請求量的情況下,註入故障的爆炸半徑很小、對線上影響極低。
但出於業務安全的思考慣性,我們在建設故障原子時基本是按照演習的思路建設:先摸清元件原理,逐個元件/業務客製原子,導致前期交付周期較長。若在控制爆炸半徑的基礎上,開放更多故障註入的自由度,註入更多、強度更大的故障,可以低成本的發現更多有價值的風險。
4.2.2 自動化與穩態辨識
自動化包括:註入故障和異常判定,當前系統支持了註入故障的自動化和簡單的穩態辨識,辨識的正確率和召回率還有空間,因此異常判定大多數仍需人工分析。自動異常判定需要較為高級的 AI 能力,很難基於某些特定規則覆蓋所有場景。若能做到全面的自動化,其它業務便可低成本落地混沌工程。另外,也可以註入大批次的組合故障,探索更多未知風險。
4.2.3 支持多類爆炸半徑的實驗
本文在多分區上部署獨立的混沌分區,來控制爆炸半徑。而對於非核心支付或者非支付的大多數業務,並沒有多分區環境,因此要在其它業務實施混沌工程,仍需結合業務安全和有效性來取舍。