作者淇公,螞蟻金服技術專家,熱愛java和一些函數式語言,長期關注系統穩定性領域

一、差旅隨想

談談系統穩定性設計

因爲base在分公司,需要經常去總部出差,所以搭乘飛機成了家常便飯,很多時候坐在飛機上會不由的感嘆,設計製造這樣精密複雜的機器的那幫人真的是了不起,他們是怎樣保證這樣一臺由無數零件組成的設備能夠穩定運轉的?

於是去簡單查閱了一些資料,瞭解到無論任何情況下,我們所乘坐的客機從生產到投入運營,任何細節都是將可靠性放在第一位的,簡單來說,體現在:

設計階段:

方案儘量簡化,冗餘設計,採用成熟經過驗證的技術,標準化,健壯性設計等等.

測試階段:

氣動力試驗,環境試驗, 可靠性與壽命試驗,真實試飛,各項極限測試等等

運行階段:

執飛前檢查,運行狀態監控,定期維護檢修.

機組:

持證上崗,定期培訓,考覈

一架飛機在雲端飛行,無數次面對氣流的顛簸,起飛降落的衝擊仍然能夠保證安全可靠,這背後從設計到製造再到維護,完全是一項系統工程, 需要極高的專業水平和責任心才能勝任, 而工程領域的實踐經驗通常都有相通性,作爲一名軟件開發人員,不禁要思考我們所開發,運營,維護的軟件系統,同樣是一項專業的系統工程, 同樣需要滿足極高的穩定性要求,面對洶湧而來的流量衝擊,軟硬件變化的影響仍然需要屹立不倒,我們需要怎麼做? 對比苛刻的航空器可靠性要求以及保障策略和手段,我們可以從中學到什麼?

二、概述穩定性保障

首先要明確穩定性保障時什麼,在我看來,系統穩定性保障的內容包括:

穩定性保障通常來講是指保障系統在運行, 運維過程中, 即時面對各種極端情況或突發事件仍然能夠提供持續的, 可靠的服務能力.

此處所指各種極端情況或突發事件包括且並不侷限於機房級故障, 城市級故障,線上故障, 線上業務量瞬時爆發, 持續快速增長, 系統服務器故障, 依賴數據庫故障, 環境數據改變, 依賴系統故障等.

此處所指持續的, 可靠的服務能力是指受影響集羣依據突發情況嚴重程度,在業務可接受的時間範圍內完成恢復或失敗轉移,繼續提供正確的服務能力以及足夠的運算能力.

看上去挺嚇人的,總結起來就是系統一旦上線運行,那麼無論面對什麼情況都儘量不要出問題,如果出了問題也要求可以快速解決和恢復.

何其複雜的要求,良好的設計, 嚴格的,全面的測試驗證,持續的運營維護,迭代,重構,升級,經驗豐富的研發維護團隊缺一不可,航空業以安全爲最高準則,我們則以系統穩定作爲底線.

三、怎麼做系統設計

民用飛行器的設計原則包括方案簡單,冗餘設計,技術成熟,標準化,健壯.而軟件系統的穩定性同樣與設計方案息息相關:

職責清晰,單一的系統,其穩定性保障的難度會小於大雜燴,功能繁多的系統,不同的業務功能,其業務特徵,業務形態,業務量,資源使用形式,依賴關係都可能不同,如果混合在一個系統中,將很難避免相互影響.

設計師在設計飛機時,會在可以達到目標的情況下,儘量選擇簡單的方案,這樣無論從成本節省還是維護效率上都有所提升,兩點之間直線最短,對於系統設計也是一樣的,一定不要過度設計和爲了技術而技術,比如一組配置數據,數據量不大,實時性要求也不高,就不要去引入分佈式緩存,變更通知,簡簡單單的JVM堆內緩存+定時刷新就可以搞定,維護簡單方便,否則技術棧的加深,維護節點的增加都會帶來更多的不穩定因素。

冗餘設計,對於飛機而言,體現在機組包括機長副機長,引擎至少雙發,操作系統至少兩套等等,於我們的系統而言,則通常體現在:

  • 數據冗餘,數據多份副本,DB一主多備,出現問題時可以快速切換.
  • 計算能力冗餘,服務器的計算能力始終保持一定冗餘,在一組服務器出現問題時其他服務器可以接替提供服務,亦或在業務量波動時可以承受衝擊。
  • 網絡,存儲或其他基礎設施冗餘,出現意外時,比如斷電,光纖斷裂時均有備用可以實現切換,快速恢復。

技術成熟,標準化,通常來說,在企業級的應用中,技術選型是非常重要的,由於對可靠性有極高的要求,因此一種技術組件或框架,中間件在引入時要充分的考慮:

  • 是否經過充分的驗證
  • 是否有廣泛的用戶基礎,有足夠有經驗的開發人員
  • 是否有完善的文檔和技術支持

標準化則比較典型的運用於系統交互協議標準化,數據模型標準化,服務標準化,標準化帶來的好處也非常顯著:

  • 規範系統之間的交互方式,便於維護,管理
  • 提升效率,避免重複造輪子
  • 降低技術學習曲線,解放人員勞動力
  • 信息理解無偏差,數據流動順暢
  • 服務約定明確,能力清晰,對接效率高

健壯性對於飛機的安全至關重要,因此飛機所使用的設備,材料都經過各種嚴格的健壯性測試,確保可靠性,對於軟件系統而言,本身是個比較大的命題,一般來講是指系統的容錯能力,無論是一次錯誤的輸出,或是一個依賴服務的崩潰都不應該影響系統自身的服務能力和正確性,這一點本身不容易做到,但也有一些手段可以輔助我們儘可能做好:

良好的編碼規範和嚴格的測試驗證,比如對異常的捕獲處理,對邊界數值的驗證避免單點依賴,無論是系統單點還是技術單點,這包括關鍵依賴服務應該集羣化,多單元甚至多地部署,設計災備方案,比如DB 的FO,交互的同步轉異步,RPC轉消息等等,保證在依賴的服務出現問題時可以繼續提供服務,同時數據可達成一致,信息可達,壓力可控。

四、風險分析

商用客機在交付前會進行一系列的嚴格測試,這些測試來源於設計人員對於飛機將來的使用場合,環境,以及可能面臨的一些極端條件所分析出的可能存在的風險而針對性設計的,要求飛機能夠承受住考驗纔可交付,對於應用系統的穩定性而言,道理是相通的,不過按道理來說,系統設計和風險分析應該放在一起討論,可是很多時候我們很難有機會重頭開始設計一個系統,那麼當我們接手一個系統時,需要對系統進行全面的風險分析,這是實施穩定性保障的基礎前提.

一般來說,風險分析需要包含幾個方面:

  • 對外提供什麼服務
  • 那些業務依賴本系統
  • 系統的上游有那些
  • 依賴的下游有那些,依賴的程度如何
  • 系統的部署結構是什麼樣的
  • 依賴什麼數據,從哪裏獲取
  • 依賴那些資源,資源使用模型時怎麼樣的
  • 日常常見的維護操作是什麼,都有誰參與等等

分析這些內容有什麼好處呢,首先可以讓我們看清系統對業務的影響情況,影響面,其次,結合日常運維動作,鏈路關係,資源使用模型可以推導各方面可能存在的風險點和帶來的後果,比如一個依賴節點耗時上漲了,帶來的後果可能是業務處理耗時整體上漲,甚至拖垮調用節點,這就是可能存在的風險點. 又比如運維人員可能會進行一些日常維護動作而縮容,這有可能導致系統出現容量風險等等.

當我們完成了風險分析,很自然的就可以進入到風險防範,治理階段了。

五、風險防範三板斧

風險預防

簡單來說就是質量+容量+灰度+回滾。

良好的質量保障是保證系統穩定運行的重要基礎,如同飛機製造過程中的質量控制,精細到每一個部件,完成後還會進行覆蓋到每一個細節的測試驗證一樣,我們的每一個迭代,每一次變更都需要有完善的質量保障體系進行覆蓋, 確保變更質量符合要求,這套體系通常包含如下內容:

  • 需求分析
  • 系統分析,設計文檔產出,評審
  • 開發自測,交付測試,聯調
  • 持續集成覆蓋
  • 代碼CR
  • 整體交付報告review

這裏面每一項的目的都是爲了減少出錯的可能,避免bug上線.

此外,系統從建設之初就應該考慮容量模型的數據是否符合預期以及高度可複用的度量手段的建立, 畢竟大家都不願意乘坐一架機翼載荷不明的飛機,對於不同資源使用模型的系統而言,其容量模型一般是不一樣的,對於一般的在線服務應用系統而言基本上都是計算密集型,容量方面主要需要關注的是 QPS-CPU-耗時 三者的關係, 我們需要知道:

  • 目標QPS下, CPU使用是否處於安全水位之下, 響應時間是否可接受
  • 多少QPS下,CPU水位達到危險狀態或耗時升高到無法接受的程度

搞清楚這兩組數據,我們就知道日常情況下的集羣容量以及極限情況下的集羣容量,可以用於指導計算資源的配置,不至於被洶湧而來的請求壓垮.

這三個因素相互制約,任何一個不達標,則整體容量不符合要求. 一般來說,獲取容量模型的手段包括:

  • 獲取單系統容量模型所進行的單機壓測
  • 獲取完整處理鏈路容量模型所進行的全鏈路集羣壓測

壓測時,需要關注的是壓測樣本的仿真度問題以及服務器配置的差異,如果壓測樣本與真實情況偏離較大,那麼獲得的容量模型可能與真實情況相去甚遠, 如果集羣機器配置差異較大,單機壓測或者不全面的全鏈路壓測都可能給出錯誤的指導數據.

然後來講一講灰度, 首先要明確的是,無論多麼經驗豐富的人編寫的代碼,經過多麼嚴格的測試驗證, 都無法百分百避免問題遺漏, 所以變更發佈一定要具備灰度和監控的能力,無論採用什麼樣的灰度策略, 大部分情況下都可以將問題的爆發控制在可控制的範圍內.一般可能採取的灰度策略包括:

  • 按用戶比例灰度
  • 內部用戶灰度->外部部分用戶->全量
  • 白名單灰度
  • 按區域/地域灰度等等

灰度階段發現的問題,可能是用戶的一些反饋,意見,可以快速迭代進行優化,解決,某些可能就是真實的線上問題,會對用戶體驗甚至資金造成影響, 這時就需要緊急回滾,因此快速回滾的能力必不可少, 這要求做到如下幾點:

  • 具備良好的代碼,數據版本管理能力,可以實現快速的替換
  • 提前分析好回滾的依賴性,避免出現鏈路某個節點回滾其他節點還保持依賴導致整體出錯。

風險預警

通常來說,我們乘坐的航班,駕駛艙裏的設備會實時的對機件的運行狀態進行監控, 地面雷達也會不斷的監控飛機的動向,一旦出現異常則進行快速應對, 我們的系統也是一樣的,必須具備對運行狀態的監控能力, 合理有效的監控體系能夠幫助我們及時發現存在的問題,進而採取進一步的措施來進行處置,這種監控體系通常是多層次的:

基礎資源監控

  • 網絡
  • 存儲
  • 服務器硬件,系統資源
  • 通用中間件
  • DNS
  • 流量調配

應用服務監控

  • 業務量
  • 來源分佈
  • 結果
  • 耗時
  • 成功率
  • 依賴調用量
  • 依賴調用成功率
  • 依賴調用耗時

應用基礎資源監控

  • 服務器數量,分佈
  • 服務器內存
  • 服務器CPU使用
  • GC情況
  • 線程池使用情況
  • DB調用量
  • DB調用耗時
  • IO
  • 磁盤佔用

鏈路監控

  • 業務整體成功率
  • 業務鏈路處理整體耗時
  • 報錯量監控
  • 問題節點監控
  • 等等內容

在這些監控內容的基礎上, 通常又要按照部署的集羣,區域,單元進行邏輯化的監控單元,便於進一步定位問題範圍.

在監控的基礎上,會配置各種各樣的報警,關注各種指標的變化情況,每當出現異動都會觸發報警,通常這些報警都是基於專家經驗人爲設置的,這樣的典型結果是一方面我們可以知道現在系統上出現了異動,另一方面是這種異動可能因爲業務發展帶來的量級變化,偶然的抖動,不同時間段的差異等等原因帶來海量的噪音,引發報警疲勞,面對這種問題,通常採用下列辦法進行優化:

多監控點,多層次關聯,低層次監控關聯高層次監控,比如監控DB調用量的監控點與業務調用量監控點進行關聯,當DB調用增加時可以知道是由於業務量上漲導致,快速給出定位原因,避免不必要的恐慌, 這種關聯的優勢還在於爲問題緊急程度提供評估, 比如某個依賴系統down掉了,對它的監控報警點關聯到整體業務成功率報警點上,如果報警信息上明確告知沒有影響到整體成功率,那麼一般無需採取一些極端的應急手段,反過來,則需要立即着手快速止血。

另一方面,引入一些智能算法,通過對業務規律,歷史數據的分析,學習,輸出一套自我更新,自我迭代的監控機制,可以自適應的識別那些常態化的變化因子,從而有效降低無效報警數量,達到精細化,高效的監控報警效果.

應急處置

所謂應急處置,則是指系統確實出現了異常情況,通過某些措施手段快速止血,恢復的過程。如同飛行員在飛機出現問題時決策返航,切換控制系統,關閉失效發動機一樣,需要快速掌握情況後決策出合理的下一步動作來消除風險。

通常在接收到監控報警後,如果產生了比較嚴重或者可能誘發嚴重問題的情況,那麼就需要進入應急階段,應急處置應該是一套明確的機制和規範,指導人員進行快速有效的應急,這包括:

人員如何分工:

誰負責排查,誰負責關注業務運行情況,誰負責信息同步,誰負責決策,誰操作止血等等,並非所有的事情都需要專人跟進,而是明確角色,可以一人擔負多個角色.

如何決策:

什麼樣的情況下,應該採用何種手段進行止血處理,影響是什麼,什麼樣的情況下可以進行恢復操作.

預案准備:

面對什麼問題可以使用什麼手段進行處置,達到止血的效果,通常而言,預案會包括回滾,降級,切換,擴容,重啓等等,每一種預案都會針對特定的問題,也可能多重預案聯合使用,視具體情況而定.

回顧覆盤:

處置完成後收集那些信息,如何總結和產出優化提升任務.

應急處置機制應該在做在事前, 團隊成員充分學習和掌握,並且每次應急後進行總結,對不足的地方進行提升,總之應急就是爭分奪秒,高效的協作和準確的處置可以挽大廈於既倒。

六、在此之外

當我們分析完系統的風險,相應的建立了監控體系,應急處置機制,是不是就高枕無憂了呢,答案肯定是否定的,事物總是在變化之中, 風險點可能隨着系統演變而變化, 監控可能隨之時效或遺漏,預案可能失效,人員經驗可能過時,精氣神可能懈怠, 如何應對? 我們還需要常態化的演練機制,不斷的吸收出現過的問題進行反覆的演練,一如飛行員要定期培訓,考覈,機組要經常進行應急,疏散等演練一樣,通過演練,我們可以達到以下效果:

  • 驗證監控系統有效性
  • 驗證預案有效性
  • 驗證團隊應急機制執行,掌握情況
  • 爲潛在問題摸索應對方案

這一切都是爲了保證整套穩定性保障的體系可以高速運轉, 而演練,應該注重如下幾點:

  • 仿真度,應該儘可能的貼近真實問題現象和觸發原因
  • 突然性,讓團隊成員在最真實的狀態下進行反應
  • 安全性,演練必須注重安全性,不能對真實業務造成影響
  • 即時覆盤,總結做的好的,不好的,不好之處加以提升
  • 反哺,用演練不斷的查漏補缺,提升整個體系保障能力的厚度

六、結束

系統穩定運行是我們開發者的底線,我本人也長期奮戰在維護系統穩定的戰線上,深知其中的艱難,敏銳的洞察力,警覺感,執行力,敬業精神是每一個穩定性保障成員的必要素質,完善的風險防控體系是我們手上的利器,守住底線,不要讓自己,讓隊友失敗。

相關文章