系統穩定性建設三件事

阿里妹導讀
本文分享了作者學習穩定性工作、構建思路、落實方案,面對問題不斷反思再推進的經驗總結。
一、背景
2024年初,我接手了內容風控團隊的穩定性負責人工作。從接手時的生疏和不熟悉,到開始學習穩定性工作、構建思路、落實方案,面對問題不斷反思再推進,現在也積累了一些經驗,藉此機會總結一下。
二、穩定性定義
為了做好系統穩定性建設,首先需要明確什麼是系統穩定性。通俗來說,系統穩定性指的是在經歷外部干擾導致偏離原有平衡狀態後,系統仍能在干擾消失後具備自主恢復到原來平衡狀態的能力。這種能力體現了系統的韌性和恢復力。
明確了穩定性的定義,下面將詳細說明建設之初我所遇到的問題及挑戰。
三、問題、挑戰及期望目標
3.1. 問題

3.1.1. 問題現狀及隱患

在今年3月初,我剛接手內容風控穩定性負責人一職時,系統面臨一系列穩定性問題及隱患:

3.1.2. 問題分析

上述一系列問題仍主要呈現為單獨的點狀問題,涉及到事前的引擎架構治理升級和對外SLA保障建設等,以及事中的監控告警體系和定位能力的建設等。經過歸納分析,我們可以將這些問題做如下分類:

僅對當前列舉的問題歸納分類,並不能確保系統的健康和穩定,單純應對當下問題難免會留下不完善之處。經過進一步諮詢、資料查閱與學習後,結合內容風控系統的特點,我將可能存在的隱患進行了進一步歸納總結,抽象形成了一套穩定性建設思路:

結合上圖抽象的穩定性建設思路再對內容風控域穩定性建設問題做思考:

這套穩定性建設思路模板涵蓋了三個主要關注事項:事前降低發生頻率、事中減少影響以及事後最佳化改進,同時包括30+個細化專案。結合現有的問題和模板的補充,透過系統治理這些問題,相信能夠有效提升穩定性,達到一個較為理想的水平。
3.2. 挑戰
將問題轉化為穩定性建設的具體事項,其中重要緊急亟需治理的部分用紅色×標示、仍需提升的用黃色感嘆號標示、以及較為完善需持續保持的用綠色對鉤標示,如下圖所示:

針對上圖中需治理的事項,面臨以下挑戰:
  • 在面對上游日呼叫量級大、且請求內容型別大小不均的情況下,如何將SLA提升至健康水平?
  • 如何合理設立應急小組和監控預警機制,以確保全面覆蓋的同時,儘量降低噪音,並提高響應時效,激發團隊的積極性?
  • 如何抽象並定義歷史故障應急定位的手段,並將這一流程自動化,以避免人工操作,提高定位時效。
  • 如何在內容風控這樣多業務形態、大流量、長鏈路、多非同步處理環節的複雜系統,在發生異常時仍然能100%按時正常返回業務結果?
  • 如何實現架構升級過程中的無感知體驗?
3.3. 期望目標
基於上述亟需治理、仍需提升的事項以及挑戰,定義出以下幾點期望目標:
1. 上游請求成功率提升一個數量級;
2. 事中應急時效提升一個數量級;
3. 解決鏈路中任何異常點導致上游卡單的問題,卡單量級周維度統計下降一個數量級;
4. 系統實現單元化架構,消除資源和容災能力瓶頸。
接下來將詳細闡述為了解決上述問題和實現目標所採取的具體措施。
四、穩定性保障三件事
4.1. 事前降發生
降發生,即降低故障發生的機率,從方案設計階段即採用面向失敗的理念來設計系統架構。具體可以再拆分三項:高可用、高質量及勤自查。

4.1.1. 高可用

高可用定義:系統能夠在長時間內持續提供服務的能力,即使在遇到故障或異常情況時,也能快速自動檢測、恢復、轉移或替代,從而保證系統的連續性和可用性,減少停機時間和資料損失。結合內容風控系統特點主要有以下幾項:

4.1.1.1. 理上游請求失敗率高的問題,消除風險隱患

進入CY24,廣告、短影片、大模型應用、遊戲、稽核標註等多項業務迎來了彈射式發展,對內容風控引擎從可用性提出更嚴苛的要求。
下面簡要介紹下內容風控引擎執行原理:簡要說明核心是動態編排的決策流DAG執行,DAG中包含N個決策節點,每個節點又對應1-N顆策略樹,樹上的葉子節點對應1-N條策略,策略依賴模型、能力及特徵左值及相應的規則進行計算、合併,最終產出風控結果,如圖:

內容風控將引擎劃分為同步計算引擎和非同步計算引擎。同步計算引擎主要負責處理那些計算耗時穩定且風險較高的策略,以便及時給出結果;而對於那些耗時較長且適合非同步執行的策略,則採用非同步分析,並透過訊息通知上游。如圖:

目前,我們的重點是解決上游呼叫同步引擎分析所面臨的兩個主要問題:
1. 日常失敗率較高;
2. 經常出現失敗率飆升的尖刺。
4.1.1.1.1. 日常失敗率較高
針對第一個表象問題進行根因分析,最初考慮了引擎中的配置是否存在不合理之處,特別是超時時間設定與上游請求超時時間之間的匹配問題。經過排查和分析,確實發現某些場景中存在這一問題。為了解決這一問題,主要進行了以下幾點最佳化:
  • 引擎超時模式產品化
上游業務型別不同,對於耗時的要求也不一樣,再加上引擎超時邏輯缺乏明確的產品化定義,所以存在業務場景接入時上游超時時間與引擎超時時間不匹配的問題。因此我們針對上游業務形態,抽象出了文字及圖片兩種引擎服務SLA保障模式,根據模式配置會動態調整上游請求在引擎中的超時規則來進行適配。

  • 策略預計算&非同步化
策略執行的耗時大頭在於規則左值的計算,例如依賴的模型、寬表等,目前引擎已支援對部分左值進行預計算。但還有部分長耗時且不支援大批次預計算的特徵仍然保持序列執行,而依賴這樣特徵的場景其實絕大多數並不需要一定在同步引擎執行,因此在產品上支援了勾選這部分特徵進行非同步化計算。
經過上述工程最佳化成功率有所提升,但離目標成功率提升一個數量級還差些,進一步分析剩餘超時case發現,這些超時情況往往與機器GC過程密切相關,因此下一步重點分析為什麼GC耗時高及如何最佳化GC耗時:
  • 定位大物件進行最佳化
想到GC耗時高首先想到的就是看下是否有不合理的大物件建立,JVM引數中有一個配置-XX:ArrayAllocationWarningSize=xxx,用來將堆中分配大物件的大小超過該值的時候,標準輸出中列印大陣列的分配堆疊,用來排查大陣列分配導致的GC問題。經過排查發現部分日誌將事件上下文轉json列印,而內容事件轉成字串部分很佔記憶體,因此第一個最佳化點就是調整不規範的日誌列印問題。
  • 最佳化調整JVM引數
經過大物件最佳化後GC時間有所下降,超時筆數也在降低,但離目標水位還有差距。進一步分析JVM引數發現適當調整:InitiatingHeapOccupancyPercent
可以平衡GC頻率及回收時機來達到降低耗時的目的,經過一系列變數控制對照實驗驗證,尋找到一個適合內容風控引擎的配置後進行了調整,成功率效果較為理想。
  • 升級JDK21
儘管成功率提升較為理想,但仍未達到我們的預期目標。透過進一步對於垃圾收集器的分析,發現JDK11之後推出的ZGC在提升GC吞吐及提效回收時間上有極大增益,主要原理如下:
ZGC使用了染色指標技術,搭配上讀屏障和轉發表,因此可以在使用者執行緒繼續執行的同時進行記憶體整理(包含了存活物件轉移和垃圾回收),這是CMS和G1都沒有辦到的。CMS可以與使用者執行緒併發執行記憶體回收但沒有進行記憶體整理;G1使用標記整理演算法但回收時就要STW。
更深層次的原理分析請大家自行查詢ZGC官方文件:
https://openjdk.org/jeps/439
經過上面一系列GC最佳化後,GC時間平均減少70%以上,上游請求成功率也提升一個數量級。
4.1.1.1.2. 經常出現失敗率飆升的尖刺
引擎經常在流量平穩的情況下出現短暫的超時量暴增的尖刺現象,即在幾分鐘內超時失敗量暴增5倍以上後又迅速回落。經排查,發現問題是由於當時機器頻繁進行GC導致的。因此,一開始是和第一個日常失敗率高的問題當做一個問題,針對最佳化GC耗時來解決,但效果並不佳。
進一步分析問題時,我們注意到了兩個線索:一是這種現象在週末幾乎不出現,二是出現時所有機器幾乎同時在頻繁進行GC。根據這兩個線索,分析問題可能與系統釋出有關。最終排查發現,問題的根源是由於關鍵詞的全量釋出導致執行時構造倉儲佔用過多記憶體,從而引發頻繁的GC導致。因此進行了關鍵詞全量構建調整為增量構建的最佳化,最佳化後尖刺問題得到明顯緩解。

4.1.1.2. 限流蓄洪功能產品化便於配置運營

預期外的上游業務流量的突增,會導致系統及下游模型等水位升高可能造成故障,之前有過類似的應急案例。內容風控引擎現已支援透過單機令牌和定時拉取及上報至分散式快取的限流模組,實現了基於業務場景維度的叢集限流功能。但對於一些高風險場景,簡單的限流返回預設透過結果會造成風險遺漏的隱患,因此引擎還具備在觸發限流後,利用資料庫分庫分表儲存事件流水,透過定時排程機制實現蓄洪洩洪的能力。
現在主要的問題是這一套限流蓄洪功能使用需要透過一個複雜度很高的配置推送才能生效,這導致除了少數技術外,大多數策略同學難以獨立完成配置。為此,我們將此功能產品化,降低使用難度。

4.1.1.3. 透過引擎事件高保能力建設,解決鏈路中任何異常點導致上游卡單的問題

現在內容風控系統是一個業務形態多、流量大、鏈路長、多非同步處理環節的複雜系統,在發生異常時不能承諾100%按時正常返回業務結果。因此需要建設事件高保機制,透過異常感知重試來解決該問題。

4.1.1.4. 系統實現單元化架構,消除資源和容災能力瓶頸

公司這幾年開始發力內容化業務,經過一段時間的創新和孵化,各類泛內容業務逐漸興起,且部分內容業務已經進入規模化發展階段,對容量水平擴充套件的訴求也日益強烈,當前我們所面臨是之前沒有實現單元化架構導致機器資源出現限制,觸達內容容量的天花板等問題,需要進行架構演進升級。

4.1.2. 高質量

高質量是一種軟體開發最佳實踐經驗的沉澱,透過設立開發規範可有效減少人為故障的發生,透過合理的系分理念,提升系統的可維護、可演進能力:

透過高質量規範建設可以提升團隊技術系統品質,減少故障發生隱患。
目前,我們已經建立了統一的編碼規範、系統分規範,以及評審、自測和釋出前集中程式碼CR的機制,這些方面做得比較好。當前亟待解決的問題是預發MR佔比較高的問題。透過與質量團隊合作,構建了預發MR的離線報表進行分析後,我們發現大家做預發MR主要有以下三個原因:
1. 線下環境不方便測試;
2. 對於正在進行的預發MR缺乏足夠的關注,例如serverless模組的釋出;
3. 統計方式不合理,例如在多分支聯合釋出時,預發階段的合併衝突解決也被視作一次預發MR。
針對上述三個原因,我們聯合質量團隊共同研究解決方案。目前,關於第一個不便於測試的問題仍在積極處理之中,其他方面已達成共識,包括提升大家對多線下自主測試的認識,以減少直接進入預發測試和MR的情況,以及最佳化不合理的統計方式。

4.1.3. 勤自查

勤自查主要是需要各應用owner對自己負責的應用上下游依賴、中介軟體、內部資源及機器水位保持日常關注:

應用的上下游依賴關係、中介軟體、內部資源和機器狀態時刻都在發生變化。因此,定期進行review是非常必要的,這可以幫助我們提前識別並解決潛在的故障隱患。基於這一目的我們定義了應用owner需關注的系統指標,並收集了相關的離線資料,製作了DI報表以進行定期推送。同時,透過每月review異常指標,激勵大家積極主動地修復系統應用中的潛在問題。
4.2. 事中降影響
降影響,即降低故障發生後的影響範圍。具體可以再拆分三項:早感知、快定位、急止損。

4.2.1. 早感知

早感知:即透過各種系統保障手段(例如監控預警)來儘早發現甚至預測系統故障。結合內容風控系統特點主要有以下幾項:

4.2.1.1. 建設應急值班機制

穩定性建設不是某一個人或少數幾個人能夠獨立完成的,僅靠少數人容易造成故障發現響應時效慢的問題,因此需要團隊每一個成員都具備相應的意識並積極參與。我們基於內容風控團隊的業務特色將團隊拆分為五個應急小組,每個小組設立組負責人:
1. 業務維度分為兩個小組:直播音影片組、大模型安全組。
2. 平臺基座維度分為三個小組:識別引擎組、能力中心組以及二三道防線組(包括傳播追溯和回溯)。
同時建立了一些配套的機制:
4.2.1.1.1. 告警觸達策略建設
各小組將根據各自的關注點建立相應的監控與告警,並將告警結果彙總至同一個群組,以實現統一管理。為確保應急告警能夠及時傳達,我們制定了一套值班觸達策略,具體邏輯如下:值班以天為輪換週期,每7天更換一組,每組由2名同學值班,分別擔任主值班和備值班。當監控系統發出告警時,會在1分鐘內透過應用DING通知主值班;如果主值班未及時響應,則在2分鐘時透過電話通知。如在10分鐘內仍無人響應,將啟動通知升級策略,及時通知備值班人員及相關小組的負責人,以減少觸達丟失的機率。
4.2.1.1.2. 應急指標建設
為了增強大家的風險意識,提高應急響應的積極性,並持續最佳化監控告警配置,我們對值班期間的離線資料進行了統計分析,提取了關鍵指標,如:分鐘級響應率、小時級完結率、告警完結率、有效告警比例以及應急噪音比例等,製作了DI報表進行定期review。其中,分鐘級響應率、小時級完結率和告警完結率能夠反映同學們的應急響應效率,而有效告警比例和應急噪音比例則透過定期review指導我們持續降低監控告警中的噪音,並進行相關最佳化,從而在減少告警干擾的同時提升告警質量。

4.2.1.2. 持續完善、降噪監控告警,提升感知時效

4.2.1.2.1. 監控告警建設
監控告警建設主要分兩個維度:
1. 基於系統指標的通用監控告警:error量級、service成功率、rpc成功率、db成功率、cal成功率、訊息傳送指標、訊息消費指標、埠可用情況、系統CPU水位及系統FGC總量等;
2. 基於業務特性的監控告警:遊事件請求成功率、下游能力成功率、關鍵業務跌0及對外給出的攔截處置量級等。
4.2.1.2.2. 降噪
我們認為,與監控告警的配置相比,更為重要的是如何平衡告警與噪音的比例,儘可能降低噪音。以下是我們常用的幾種降噪措施:
1. 減少重複告警:大多數告警的配置並不是由單獨個人完成的,往往需要多個人長時間的協作。在這個過程中,難免會出現一些重複或相似的告警。透過合併和統一這些告警,我們可以有效降低噪音。
2. 分級告警:採用不同的告警級別,以確保高優先順序告警能夠及時處理。例如,對於一些上游請求耗時升高及系統高保重試異常的告警,我們可以在夜間進行降噪,只保留關鍵的P0級告警。
3. 合理的閾值設定:之前在內容風控系統中,有一個關於外部攔截量上漲的告警,配置條件是數量。然而,隨著業務量的增加,當請求與攔截的同比上漲時,實際上可能是一個合理的現象。因此,我們將攔截告警配置分為兩類:對於呼叫量較小的請求,仍然按照數量設定預警條件;而對於呼叫量較大的請求,則採用攔截比例作為預警條件,以達到降噪的目的。
透過應急值班機制及監控預警機制的建設及實施,應急發現時效基本達到提升一個數量級的目標。

4.2.2. 快定位

定位故障原因的時效在事中尤為關鍵,快速的定位能力能極大減少故障帶來的影響。

為了提高故障發生時的定位效率,我們回顧了歷史上內容風控團隊的應急案例,發現主要問題集中在兩個方面:
1. 上游請求超時量激增。
2. 非同步引擎訊息大量積壓。
針對這些應急案例,之前的定位手法通常需要人工開啟監控篩選排查具體原因,比如是哪個業務的呼叫量增加導致的問題?還是某個下游服務響應時間變長所致?這種逐個場景分析的方法效率較低。
因此,我們特別針對上述兩點設計了綜合監控方案。當檢測到上游請求處理時間增長或引擎訊息積壓觸發警報時,系統將自動檢查相關業務場景下的呼叫次數、失敗率以及響應時間是否也有所上升,並同步監測下游服務是否存在響應延遲情況。透過這種方式,可以更加快速準確地識別出故障根源所在。
這樣的改進不僅提高了故障診斷的速度,還減少了人工干預的需求,從而使得整個定位流程變得更加高效可靠。
透過聯合告警定位能力建設,應急定位時效基本達到提升一個數量級的目標。

4.2.3. 急止損

急止損:“止血”大於“修復”,故障發生後第一反應永遠是“優先止損”。止損的時效提升能極大減少故障帶來的影響。

預案在止血過程中是至關重要的。我們在預案的建設方面已經有了較為完善的基礎,而核心問題在於讓更多的同學參與到預案演練中、以及將核心預案自動化,確保在關鍵時刻有更多的人可以執行預案、以及核心預案可自動化,提升止血效率。

4.2.3.1. 定期演練,提升止血時效

與高可用團隊合作,每季度進行一次預案演練。

4.2.3.2. 核心預案自動化

在預案中,最關鍵的是因為策略或引擎故障所導致內容攔截量級暴漲的降級預案。在許多情況下,當故障發生時,技術團隊需要依靠經驗來判斷是否可以執行相關操作。通常我們必須先與場景owner確認情況,才可以進行推送,而這種時間差本身就潛藏著重大的使故障升級的風險。因此,我們決定將該功能產品化自動化,供場景策略同學進行運營。

透過預案演練及自動化,應急止血時效基本達到提升一個數量級的目標。
4.3. 事後優改進
優改進:及時進行復盤,以實現故障閉環,並不斷提升穩定性建設水平。

之前,我們在組織覆盤機制的建設方面還有待完善。因此,除了故障後的AAR覆盤會外,我們還透過每月的月會,對與穩定性相關的事項和資料進行內部分析與總結。會議將重點關注各應用的健康狀態、各組的應急資料指標以及對進一步完善穩定性建設的思考與討論,以推動穩定性建設的持續最佳化和進步。
五、成果
1. 上游請求成功率提升一個數量級;
2. 事中應急時效提升一個數量級;
3. 解決鏈路中任何異常點導致上游卡單的問題,卡單量級周維度統計下降一個數量級;
4. 系統實現單元化架構,消除資源和容災能力瓶頸。
六、總結展望
在進行系統穩定性學習建設的過程中,提升了自己的“系統化思考問題”及“透過現象看本質”的能力。穩定性建設過程中會遇到許多問題,而這些問題往往只是一層表象。如果我們沒有進行深入的根因分析,便急於尋求解決方案,就很容易陷入思維誤區,誤以為在努力解決實際問題,甚至因此獲得成就感。實際上,我們可能只是創造了本不存在的問題。舉個例子,我在處理風控引擎超時尖刺時就經歷過這樣的情況:
引擎經常在流量平穩的情況下出現短暫的超時量暴增的尖刺現象,即在幾分鐘內超時失敗量暴增5倍以上後又迅速回落。經排查,發現問題是由於當時機器頻繁進行垃圾回收(GC)導致的。因此,我們提出了透過調整JVM引數來降低GC時間和頻率的解決方案,但經過一週的調整觀察,發現最終效果不佳。
進一步分析問題時,我們注意到了兩個線索:一是這種現象在週末幾乎不出現,二是出現時所有機器幾乎同時在頻繁進行GC。根據這兩個線索,分析問題可能與系統釋出有關。最終排查發現,問題的根源是由於關鍵詞的全量釋出導致執行時構造倉儲佔用過多記憶體,從而引發頻繁的GC導致。
經過團隊小夥伴的齊心協力及高可用、SRE、質量、策略團隊的鼎力支援,使內容風控域的系統慢慢達到了比較健康的水位。但隨著接入業務逐漸增多,靠一個大而全的引擎來支撐風險逐步增高,未來需要推進架構進一步升級,提升可擴充套件性,建設面向泛內容的、面向OU業務可實現安全運營模組靈活組裝的識別決策引擎。
使用Elasticsearch的向量檢索能力進行個性化推薦
在電商領域,個性化推薦系統是提高使用者滿意度與銷售轉化率的關鍵工具。本文將探討如何利用Elasticsearch的向量檢索能力,實現商品個性化推薦,助力電商平臺提升使用者體驗和業務增長。    
點選閱讀原文檢視詳情。

相關文章