穩定性實踐:限流 & 降級
當面對極端的業務場景時,瞬時的業務流量會帶來龐大的壓力,可能還會大大超出系統可負載的容量
無限制的通過 resource scale out 來提升系統可負載容量為無論從技術 or 成本投入角度,這樣做都是不划算的,也是不現實的
因此可以透過
限流降級
的手段,以保障承諾容量下的系統穩定;為某些功能加上 feature gate,在必要時可以關閉特定功能,在業務量達到高峰時,只保障核心業務功能,非核心業務功能就關閉
限流 & 降級是什麼?
限流:根據某個應用或基礎部件的某些核心指標,如
QPS
或並發數量
,來決定是否將後續的請求進行攔截。假設一秒的 QPS threshold 為 200,超過即攔截 & 回應錯誤訊息
降級:通過判斷某個 application or component 的服務狀態是否正常,來決定是否繼續提供服務。
例如:在某段時間內,Response Time 超過 50ms 的次數大於 N 次,則會短暫的關閉服務,等待一段時間(e.g. 5s~10s)後重新開啟
如何進行限流?
最常見的就是從 traffic 入口端就作限流了! 例如:
Nginx 限流:作為最常被使用的 reverse proxy,可以透過以 QPS, 並發數量、CPU 使用率作為限流的指標
API Gateway:同樣也是要監控要作為限流的指標,自動進行 traffic routing policy 的調整
其他應用層 & infra 層的限流,就需要跟開發同仁一同配合才比較容易完成,有機會研究到再來寫….
實現限流 & 降級的困難之處
困難之處主要是兩個部份:
Technique Stack 的統一
這牽涉到大量標準化建設的工作,需要與開發同仁一同進行技術選型、定義規範 …. 等等,若 technique stack 不統一,限流 & 降級就幾乎不可能落地
對於每個應用的限流降級策略可以精準掌握 & 配置
這需要對業務 & 應用有深入了解,並經過複雜的測試才能評估出一個正確的數字;而且重要的事情是,限流 & 降級是一個動態 & 不斷完善的過程,因為資源動態管理絕對不是可以一步到位的
由於改善是不斷持續的,所以當整體系統規模達到一定程度時,當已經無法使用人力來評估所有事情時,就必須引入機器學習 or 人工智慧這一類的技術來協助了!
穩定性實踐:開關和備案
上一個部份提到的限流降級的方案,是針對服務層面的,也就是對服務本身進行限流 & 降級;而另外一個可從業務角度來出發的,則是開關
& 備案
。
什麼是開關 & 備案?
開關
開關,這個概念更多是業務和功能層面的,主要是針對單個功能的啟用和停止進行控制(可透過 feature gate
的方式來做),或者將功能狀態在不同版本之間進行切換。
從業務層面舉例,假設以一個雙11促銷的例子來說,只保留交易鏈路的核心功能,先暫時關閉非必要功能,例如:商品評論….這樣的作法就是業務功能開關的實現。
從功能層舉例,一般系統架構中為了提昇效能,可能會有 cache tier 的存在,但如果因為 cache tier 發生問題,可以透過功能開關的方式,bypass cache tier,讓資料直接轉進資料庫。
備案
所謂的備案
,是為讓應用或業務進入到某種特定狀態,所預先設計的複雜場景(or 方案),而這個場景通常會透過開關
、限流
和降級策略
的組合技來實現。
例如:例如上面雙11促銷的例子,除了關閉商品評論外,可能還會需要關閉商品收藏提示、商品推薦…等功能
這一類的調整通常不是很單純的,而在不同的情況(or 場景)下,用來應對的 開關
、限流
、降級策略
的組合可能都會完全不同;因此透過備案
的設計,可以針對特定的事件一次進行開關
、限流
和降級策略
的相關處理,在管理維護上就會容易很多!
因此備案
的管理也是保持整體系統穩定性很重要的一環。
穩定性實踐:全鏈路追蹤系統
隨著微服務和分散式架構的導入,各類和基礎組件形成了網狀的分佈式呼叫(調用)關係,這種複雜的調用關係就大大增加了問題定位、瓶頸分析、容量評估以及限流降級等穩定性保障工作的難度,因此才會產生了全鏈路追蹤
這一類的 solution。
如何產生請求鏈路
全鏈路追蹤的核心技術關鍵就是 TraceID
,當 request 從接入層進來時,這個 TraceID 就要被創建出來;或者是通過 Nginx 插件方式創建放到 http 的 header 裡面;或者是通過 RPC 服務化框架生成;在後續的 request 中,TraceID 必須能夠被框架傳遞到下一個被呼叫的功能。
有了這個 TraceID,就可以將一個完整的請求鏈路給串聯起來了
問題定位和排查
全鏈路跟蹤系統,要解決的首要問題就是在複雜的服務調用關係中快速準確地定位問題,大概有以下兩類:
瓶頸分析
異常錯誤定位
服務運行狀態分析
透過收集大量個請求 & 調用數據後,可以有效的分析出下面幾類訊息:
服務運行的品質狀況
應用和服務依賴關係
依賴關係資訊是作為未來進行
容量壓測
和限流降級
這兩個工作所必要的資訊,也可以作為 scale out 的依據依賴關係的服務質量
業務全息
一般來說,全鏈路跟蹤的應用通常是在技術層面,用來定位“應用或服務”的問題,或者是應用或服務間的依賴關係等等。
但其實也很適合用來作為業務鏈路的分析,當業務在不同的階段發生問題時,同樣都是透過像是 TrackID + 訂單 ID + 用戶 ID ... 等
這幾類訊息來加入業務相關問題的排查。
故障管理:理解, 定級, 定責、應急
“SRE:Google 運維解密” 給我們的啟示
SRE 的崗位職責在很大程度上就是應對故障
理解一個系統應該如何工作並不能使人成為專家,只能靠調查系統為何不能正常工作才行
面對故障應有的態度
系統正常,只是該系統無數異常情況下的一種特例
故障,是一種常態,任何一個軟體系統都避免不了;當業務量越大,系統越複雜,問題和故障就越多,出現故障是必然的
因為我們無法杜絕故障,所以必須 Design for Failure;應該考慮的是,怎麼讓系統更健壯,在一般的問題面前依然可以穩定提供服務,甚至故障後也可以快速恢復
上面提到的
限流
、降級
、開關
、備案
… 等手段,本質並非完全避免故障,而是為了能夠更有效面對故障一般大型往站在
故障隔離
、快速恢復
、容錯切換
這些部份都做的很好,即使小問題發生也不會影響主要的服務
故障發生後的調整
永遠不要將注意力放在故障本身上,一定要將注意力放到故障背後的技術和管理問題上去;深究原因,其實故障發生的原因,通常是技術和管理上的問題累積到一定程度後爆發出來的
故障後的反思;人員技術不到位? 人為操作太多? 自動化不夠完善? 發佈後無法快速 rollback?
發生故障無法快速恢復的反思; 監控不到位? 告警太多導致人員麻痺? 定位問題的效率低? 故障隔離不夠確實? 故障備案無法落實?
任何一個故障的原因都可以歸納到具體的技術和管理問題上,通常在回頭審視並聚焦在故障案例上的過程中,都可以得到一個個非常具體的改善方案
反問自己:下次出現類似問題,怎麼才能更快的發現問題,更快的恢復業務?即使這一次的故障處理已經做得非常好了,下次是否可以有更進一步的改進?
面對故障的管理態度
管理者要先自我反省,一昧究責對解決問題沒有幫助
故障發生就表示整體上(不論系統 or 管理制度)有存在不完善的地方或漏洞,認真思考,找出來並修正
強調技術解決問題,而不是單純地靠增加管理流程和檢查環節來解決問題,技術手段暫時無法滿足的,可以靠管理手段來輔助
定責的過程,是找出根因,針對不足找出改進措施,落實責任人;定責的目的,是責任到人,並且負責人能夠確實認識到自己的不足之處,能夠主導改進措施的落地
絕大多數的嚴重故障都是因為無意識或意識薄弱導致的,並不是因為單純的技術能力不足等技術因素
如果大家意識到位,能夠謹慎小心,絕大多數因為人為疏失造成的低級錯誤都是可以避免的
管理者一定要對故障有一定的容忍度,因為員工努力做事的積極性一旦被打擊,變得畏首畏尾,也就不會有什麼技術進步和突破了
如果定責跟績效強掛鉤,團隊內成員就有極大可能陷入恐慌、質疑、挑戰以致最終相互不信任的局面
管理者除了關注故障本身之外,還要考慮得更加全面一些,要關注到人的感受,關注事情的前因後果,只有這樣,在管理執行過程中才會讓員工感受到尊重和信任
對故障要有正確和理性的認識,既不能放任不管,也不要談之色變;同時我們也需要科學的管理方式,跟業務結合,制定出對應的故障等級和定級定責制度
在日常要做好各種備案和模擬演練,當故障真實發生時,能夠做到冷靜處理和高效地組織協調
故障緊急處理 & 復盤
故障緊急處理
第一原則:優先恢復業務,而不是定位問題
業務恢復備案的執行不能僅僅在故障發生時才執行,而是應該把故障模擬和恢復演練放在平時
關於故障模擬,可以試試看 Netflix 的
Chaos Engineering
組織中要有”技術支援”的角色;當故障發生時,對內,要有效組織技術團隊的集中和協作;對外,負責對接業務部門同步相關訊息,同時消除各方對技術團隊和故障處理人員的干擾
故障緊急處理要注重平時的演練,注意建設各種工具和平台,同時要盡可能地考慮和模擬各種故障場景
故障復盤
復盤的目的是為了從故障中學習,找到我們技術和管理上的不足,然後不斷改進
切忌將復盤過程和目的搞成追究責任或實施懲罰,這對於團隊氛圍和員工積極性的打擊是非常大的