作者介紹
衛旋,B端技術中心資深開發工程師,S12技術保障項目總負責人。
一、前言
英雄聯盟全球總決賽是一年一度最為盛大的電子競技比賽,在國内關注度極高。11月6日,DRX戰隊以近乎奇迹的方式,一路從入圍賽披荊斬棘拿下了S12全球總決賽的冠軍。相當勵志,恭喜DRX!
B站作為今年S12的官方直播渠道,哔哩哔哩賽事直播間實時人氣一度超過3.1億。如何保障整個S賽洪峰流量下系統的穩定性和流暢性,給我們帶來了巨大挑戰。
為此,我們在7月底成立了S12技術保障專項,展開了為期3個多月緊鑼密鼓的技術籌備,我們的目标是可以實現“喝茶保障”。
二、如何實現
經過盤點,我們把S12技術保障依賴的各項工作拆分為賽前、賽中、賽後三個階段,如下圖:
1、項目啟動
S12技術保障需要公司多個技術團隊之間的緊密配合,涉及業務研發、SRE、基礎架構、DBA、大數據等近300人。從上遊業務充分搜集S12相關資訊後,我們召集所有相關團隊負責人召開了項目啟動會,最終在S12技術保障目标上達成一緻,争取做到全局步調一緻。
2、資源預估
1)貼合業務
為了發揮資源的最大使用價值、提高資源利用率,我們與上遊業務對齊了業務目标PCU(最高在線用戶數)、後續宣發策略和規劃,方便技術側及時介入準備、做出合理的資源估算。
2)合理估算
從B站SRE容量平台查詢到去年S11服務器峰值用量a、去年8月日常峰值用量b,粗略算出同期增長系數delta=(a-b)/b+1。
同時查詢到今年8月份日常峰值用量c,服務器當前可用量d。因為我們要求服務器容量安全水位在40%以下,所以缺口資源量=c*delta/0.4-d。
産品功能在保障過程中也會有增加,因此這部分增加的功能所需的資源支持會在單獨評估資源缺口後追加申請。
3、資源池治理
去年以前,直播資源池都是直播專屬、與其他部門獨立的,當直播資源池資源用盡後,需要從其他資源池協調機器->網絡測試->機器初始化->重新打label入直播池,全程人工、非常低效,經常導緻線上業務發布或擴容阻塞、影響應急響應效率。
從全站視角看,大型賽事直播結束後大量用戶會從直播間轉向社區其他服務(稿件、評論、專欄、動态等),類似“潮汐流量”,這部分服務器冗餘可以通過合池來“降本”。合池的前提是機器運行時的标準化:
1)服務去CPUSET
由于直播的實時性和對延遲的敏感性特征,我們的業務場景無法接受高概率的CPU Throttle帶來的超時。大量服務使用了CPUSET的綁核策略,CPUSET無法資源共享、無法合池、造成一定的資源浪費。
内核同事協助排查後發現,PHP服務的高概率CPU Throttle是因為同時并發執行的R進程過多,導緻CPU Quota被擊穿。排查PHP基礎庫發現,直播PHP服務使用了Swoole多進程模型,基礎庫會在每個Worker進程内設置一個定時器用來更新配置,1s檢查一次,多個進程大概率會在同一時刻被喚醒。修複方案有兩個:1)打亂進程定時器執行的随機性,減少“碰撞”;2)基于inotify進行配置更新,廢棄基礎庫定時器。因為業務代碼裡也大量使用了定時器用來對直播熱點數據做内存預加載,所以最終是采用了方案1,更新基礎庫後效果非常明顯。
protected function funcWorkerStart()
return function (\swoole_server $Server, $iWorkerID) {
// 部分服務會在init_callback中注冊worker timer做配置加載
// 但是會帶來并發R過多導緻cpu throttle,此處做下随機sleep 10-500ms
mt_srand((microtime(true) + posix_getpid()) * 10000);
usleep(mt_rand(10000, 500000));
Main::init();
//配置文件定期加載
$config_reload_cb = function () use ($C, $Server, $iWorkerID) {
app(Metrics::class)->flush();
// load config...
// config check...
// reload worker...
//注冊定時器
swoole_timer_tick(1000, $config_reload_cb);
對于Golang服務,我們引入了automaxprocs來自适應調整在Linux CFS調度模式下的GOMAXPROCS,并對所有Go服務做了代碼lint檢測。
2)宿主機内核升級
直播部分老機器内核版本過低無法參與合池,并且存在cgroup洩漏問題[1],造成業務超時抖動。為了合池後不影響其他部門在線業務應用,需要對老内核機器進行内核升級。
B站操作系統團隊統一了内核版本,根治了困擾業務已久的cgroup洩漏問題,同時基于Group Identity對在離線業務混部做了CPU隔離優化。
完成直播PAAS合池後,緩解了部門之間機器多份冗帶來的資源浪費。在線業務使用B站SRE容量管理平台按需分配,大大提高了資源利用率。
4、業務場景拆解
1)确定保障範圍
B站直播經過8年的發展,已經具備了多樣化的直播間玩法、能力,可以支持不同類型直播場景。今年的S12我們也推出了很多新玩法,涉及的各項能力要在對應的後台配置好後才會呈現給用戶,不同的功能玩法由不同的技術團隊支持,所以首先要确認S12用到的已有能力和新增玩法(共30+個),圈定保障範圍。
2)确定場景分級
分級标準如下:
① P0
部門核心用戶場景所對應業務: 需滿足月日均DAU >= xx W; 如不滿足條件,降級到L1
部門營收業務:需滿足月日均營收 >= xx W;如不滿足條件,降級到L1
雖未達到上述要求,但業務屬于公司戰略級方向
強依賴下遊業務
② P1
部門L0業務主場景使用中依賴的主要業務
核心的二類業務
不滿足L0的部門核心用戶場景所對應業務
不滿足L0的部門主要營收業務
強依賴下遊業務
③ P2
部門給用戶提供的其他業務
強依賴下遊業務
如上所示,我們從DAU、營收數據、依賴等維度定義了服務的分級标準,按照場景拆分确定保障等級。最終根據S12涉及到的30+個功能拆解出10個P0場景、16個P1場景、9個P2場景。
對于P0和P1的場景要重點覆蓋混沌工程測試、客戶端性能測試、服務端性能壓測、生産多活演練、可觀測監控等,保證服務架構高可用。
3)梳理場景地圖
① 定義
場景拆解後,針對單一場景将關聯的業務邏輯(微服務調用關系、接口依賴等)進行全局梳理形成場景地圖,幫助場景負責人和決策者快速了解服務本身的依賴情況。
② 梳理規範
場景名稱:xxx
場景等級:P0/P1/P2
場景介紹
方式:通過抓包、代碼翻閱、負責人确認的方式明确下述内容
方法:5w2h法(Who/When/Where/What/Why/How/How much)
場景依賴:接口、服務、緩存、數據庫、消息隊列
有了場景地圖,對S12的技術治理和優化會更有針對性。整理場景地圖的過程,一方面加深了研發、測試對于場景邏輯的認識,一些曆史問題也會變得清晰;另一方面這些元數據有助于後面各項技術架構優化、監控元數據的校準。
5、高可用架構
分布式架構下微服務之間相互調用十分複雜,一個點位故障極有可能影響整條鍊路的穩定性,為此我們做了長足的架構演進準備。
1)單點治理
分布式架構下,單點本身不具備容災能力,最容易出現問題。應該優先處理掉,主要有:
應用單點:要求所有應用都應該多實例部署(>2)。
JOB單點:基于XXL-JOB二次開發直播分布式任務調度系統,可以有效解決JOB無法多實例分片執行的問題。
資源池單點:直播PAAS資源池單宿主機巡檢,避免機器單點故障後導緻應用無法重新調度成功。
2)高在線自适應保護
千萬直播場景下,一場直播結束會有大量用戶退出直播間回到流量入口頁,對其他網關及下遊帶來數倍的壓力放大。因為Prometheus監控有采集窗口,實際的請求“毛刺”比下圖所示還高。從流量轉化數據上看,其實80%的請求是不必要的,用戶可能已經關閉APP了。
針對這類Case設計了高在線自适應降級保護方案。通過服務端與客戶端協議打通,直接從源頭上避免不必要的用戶熱點行為、對後端服務器的流量沖擊。
目前已經上線的保護策略如下,識别到當前直播間熱點後:
退出直播間不自動刷新流量頁
針對不重要的KV配置等請求,做随機延遲打散
針對廣播集中觸發接口熱點請求,做随機延遲打散
動态調大離線數據上報間隔,降低服務器壓力
API Gateway限流後自動觸發客戶端流控
3)混沌工程
在生産環境中運行分布式系統,難免會有各種不可預料的突發事件、故障發生,而微服務之間相互依賴,可能會産生異常連鎖反應。我們應該緻力于在這些異常行為被觸發前,盡可能多地識别風險,然後針對性地加固防範,從而避免故障發生時所帶來的嚴重後果。
混沌工程正是這樣一套通過在分布式系統上進行實驗,主動找出系統中脆弱環節的方法學。這種通過實證的驗證方法可以為我們打造更具魯棒性的系統,同時讓我們更透徹的掌握系統運行時的各種行為規律,也能在這個過程中及時針對性的補齊系統預案。
B站從去年開始引入混沌工程,基于chaosblade二次開發,融合監控、問題管理形成初步滿足業務微服務治理的故障注入平台。但漸漸發現chaosblade隻能控制端口級别的故障,爆炸半徑過大,影響較大無法在生産環境執行。今年自研了控制粒度更細、爆炸半徑更小的混沌演練平台,可以控制到接口、用戶粒度的故障。詳見下圖:
針對S12核心L0/L1場景,我們在進房、送禮、發彈幕、首頁等場景進行了故障演練、紅藍對抗,主動發現并治理核心鍊路上的幾類非預期問題:
代碼問題,弱依賴被錯誤地實現為強依賴,導緻核心鍊路不通;
弱依賴未考慮降級方案,用戶體驗不佳;
代碼問題,對于弱依賴的降級方案不生效;
對于強依賴故障,客戶端能否做到容錯、友好提示,各端降級體驗是否一緻。
4)同城雙活
機房故障往往是災難性的,會大大降低用戶體驗甚至出現客訴,對用戶和公司來說都是巨大損失。多機房failover能力顯得至關重要,我們對直播核心業務場景實現了同城雙活(首頁、進房、送禮、預開播等),保證在機房失聯、斷電、失火等極限情況下,可以快速決策并切流,最大限度保證用戶體驗不受損。
吸取去年“B站713故障經驗和教訓”,SRE平台和基礎架構團隊研發了 Invoker多活切流平台。經過多次生産切流演練驗證,單次切流平均時效5分鐘内。大大提高了切流效率,避免故障影響面持續擴大。
5)網關遷移
直播第一代API Gateway是基于Envoy二次開發,部署在IDC物理機。資源預估出現偏差時臨場擴容非常耗時,需要服務樹挂載->審批->機器初始化->運行時初始化->灰度->接量→測試→SLB灰度→SLB全量,平均耗時30分鐘+。
去年S11總決賽現場踩過這個坑,當時靠手速擴了20分鐘才擴上8台,擴完之後一波突發流量差點兒炸了,CPU峰值90%了,好險!
同時Envoy網關C++編寫、代碼結構十分複雜、調試困難、很難維護,無法一鍵部署。今年我們将核心服務的BFF(Backend For Frontend)全部遷移到新的自研Golang API Gateway。主要有以下優勢:
支持容器化部署
支持自動彈性伸縮HPA,分鐘級别即可完成擴容!
具備快速便捷的控制面能力:限流、降級
HA:支持邏輯/物流集群隔離
支持全鍊路灰度
目前該項目已經開源,感興趣可以學習:
6、性能壓測
經過前面的優化,我們初步保障了整個技術底座的抗故障能力,接下來會通過幾輪周期性壓測來驗證核心業務場景的極限QPS能否達到要求,未達标的要分析出瓶頸并做技術優化/擴容。
1)壓測目标
每年大型賽事活動結束後,我們都會對比賽期間的關鍵數據做存檔,方便對明年目标值做出合理預估。依據去年業務數據(在線人數、營收數據)增長比例和核心接口峰值QPS,結合接口實際調用時機,很容易估算出今年接口預期QPS。
假設去年同時最高在線N,A接口峰值QPS=a(A接口進直播間必調一次、和在線人數線性相關),前面我們和上遊業務方對齊業務數據目标(同時最高在線=M),則今年A接口預期要扛QPS = a *(1 +(M-N)/ N)
2)壓測方案
通過抓包、代碼翻閱整理出今年S12核心場景最新的接口依賴和調用時序關系(是串行還是并行),B站自研的壓測平台Melloi支持對同一個場景的相關依賴接口進行編排。
今年的S12新增了很多用戶玩法功能給用戶帶來沉浸式的觀賽互動體驗,涉及很多寫接口的壓測,可能會對生産環境造成數據污染,産生輿情和客訴。
B站在去年自研了全鍊路壓測的方案,通過全鍊路壓測标識Context傳遞,在數據寫入層的SDK做攔截策略,将壓測寫流量轉發到“Mirror數據隔離層”,實現壓測數據隔離。壓測結束後,壓測平台聯動數據庫、緩存、消息隊列等數據平台,快速回收數據。
S12送禮、心跳等直播核心寫場景就采用了這個方案,通過對場景相關鍊路的上下遊改造,借助于全鍊路壓測平台真實摸底了數據庫和異步JOB/Consumer的負載上限情況,設置了合理的限流,有效地保障了大型活動中寫服務的穩定性。
3)壓測執行
為了壓測數據的真實性,我們選擇低峰期在生産環境進行集中發壓。雖然是在低峰期壓測,但還是有一些正常用戶流量,所以一定要注意避免壓死整個系統:
開始要慢慢施壓且壓測時間短一些(比如1分鐘),以防止出現問題。
緊盯各項監控(服務的監控,Redis,Mysql,Tidb,Databus等),如果有異常要立即停止壓測。
資源使用逼近極限,需要停止壓測。
記錄壓測過程中不同壓測QPS下各項資源的壓力情況,以供後續分析。
4)壓測報告
壓測後我們會系統整理壓測報告:壓測結果、目标Review、問題跟進等。
① 常見問題
② 擴容最佳實踐
壓測結束後,根據如下公式合理估算要擴容的副本數。
7、保障預案
保障預案主要分為兩個方面:業務層和技術層。
1)業務預案
通過場景地圖梳理、混沌工程、性能壓測發現并治理了很多技術風險點,回看這些問題關鍵鍊路的技術優化,大多數鍊路降級調整依賴各種配置:服務配置、KV配置、上下遊的配置。為了保障在整個S12進程中及時響應、關鍵鍊路不出問題,我們整理了各個場景中可能需要臨場執行的各項預案。
我們針對15個S12核心場景做了保障預案,部分預案需要多個場景負責人進行聯動、協同,會在線下線上做預案演練并驗證有效。
2)技術預案
① 網關限流:結合前期壓測的QPS,配置一個合理的限流QPS
② 服務Quota限流:支持按Zone、Caller進行限流
③ 網關降級:支持按PATH和Query/Header進行直接降級,不會将壓力傳遞到業務服務BFF
④ 資源彈性
HPA:全稱是Horizontal Pod Autoscaler,水平自動伸縮。當業務POD CPU/内存使用率超過設定阈值後,自動觸發擴容,無需人工幹預。
混合雲:防止自建IDC機房資源用滿,自動彈到第三方混合雲資源上,充分保證了資源可用。
8、質量把控
S12八強賽後,我們啟動了S12強管控升級。強管控期間,線上變更需要謹慎并報備到S12技術保障項目組進行Review把關。具體分為兩個階段:
9、現場保障
1)可觀測性
往年的大型賽事保障活動,投屏的監控大盤無法直觀發現系統問題,業務監控遍布在各個角落,排查問題非常不便。今年我們首先基于場景地圖梳理出了S12 L0/L1場景的核心依賴:
接口
應用
數據庫
緩存
消息隊列
然後圍繞業務核心指标PCU(最高在線用戶數)、核心場景SLO、核心應用飽和度三個維度制作了新的健康監測監控大盤,1分鐘自動更新一次。
① 業務核心指标PCU
直播大部分系統和PCU線性相關,一旦有波動要立即關注下遊負載情況。
② 核心場景SLO
作為結果指标,對于微服務故障有着決定性的指導作用,出現波動一定是有問題了。對B站SLO體系建設感興趣可以閱讀:要是還沒搞明白SLO,你算哪門子SRE呢?
③ S12核心應用飽和度
作為預警指标,可分為三個檔位:
紅:異常,需要立即介入處理
橙:偏高,需要關注
綠:健康,無需關注
2)告警協同
保障現場出現最多的問題就是告警了,我們目前的告警存在告警等級不明确、告警接受人不準确、處理狀态不透明、告警風暴的問題,長期會基于SLO做告警治理。短期我們自研開發了一套告警應急協同平台,方便研發、SRE協同處理告警,一目了然。
支持場景管理
支持告警訂閱:按告警ID
支持告警過濾:按告警ID、按告警權重
支持告警聚合:相同告警10分鐘窗口内自動聚合
支持告警處理協同:告警處理流轉狀态一目了然,方便協同
3)現場值班
① 現場指揮官
問題優先級判斷
應急響應
技術判斷和決策
② 值班人員
業務:運營、審核
技術:研發
基礎架構:SRE、DBA、網工
三、總結展望
今年是我加入B站的第5年,回想前幾年S賽技術保障現場大家手忙腳亂地處理告警(擴容、限流、降級),現場非常混亂。即便是直播結束,告警和問題反饋也一直不斷。今年我們通過一系列的技術升級(内核升級、去CPUSET、合池、網關容器化遷移、同城雙活、HPA)和服務治理(混沌工程、全鍊路壓測、告警協同治理),保障了整個S12直播過程中技術系統穩定、流暢,沒有出現任何需要主動限流、降級、熔斷等對用戶有損的技術幹預手段,給用戶帶來了極緻的觀賽和互動體驗,實現了技術人夢寐以求的“喝茶保障”。後續我們會對技術保障過程中的各個環節進行複盤,持續打磨技術中間件和平台、建設多活單元化、全鍊路壓測覆蓋、優化資源池調度、全面推進B站基礎設施雲原生落地。
>>>>參考資料
作者丨衛旋
來源丨公衆号:哔哩哔哩技術(ID:bilibili-TC)
dbaplus社群歡迎廣大技術人員投稿,投稿郵箱:editor@dbaplus.cn
有話要說...