直播房間服務(wù)基于CQRS的架構(gòu)演進(jìn)實(shí)踐
引言
房間系統(tǒng)是直播業(yè)務(wù)的“基石”,開(kāi)播和看播兩大體系都是圍繞房間場(chǎng)景展開(kāi)。
房間系統(tǒng)架構(gòu)也經(jīng)歷一系列的升級(jí)和挑戰(zhàn),從房間讀多活、混沌流量治理、熱點(diǎn)發(fā)現(xiàn)、多級(jí)緩存等,支撐了S11破千萬(wàn)PCU的流量洪峰沖擊。
為了應(yīng)對(duì)業(yè)務(wù)更大的挑戰(zhàn),基于CQRS思想,分離大流量的用戶(hù)高讀場(chǎng)景(Query)和注重?cái)?shù)據(jù)強(qiáng)一致性的開(kāi)播創(chuàng)建房間等寫(xiě)場(chǎng)景(Command)。對(duì)于用戶(hù)端可以無(wú)狀態(tài)無(wú)限制的擴(kuò)容服務(wù)副本,做到支持更大線(xiàn)上用戶(hù)同時(shí)在線(xiàn)的目標(biāo)。
背景
直播業(yè)務(wù)的技術(shù)服務(wù)體系也實(shí)踐過(guò)從單體到微服務(wù)化的演進(jìn)之路,以技術(shù)視角看微服務(wù)體現(xiàn)單一職責(zé)和關(guān)注分離的思想,從大單體應(yīng)用的進(jìn)程模塊拓展到分布式的應(yīng)用服務(wù)模塊化。同時(shí)微服務(wù)也是有額外成本的,微服務(wù)的拆分思路不僅僅是技術(shù)層面,更多會(huì)取決于組織和團(tuán)隊(duì)(以及組織如何去看待業(yè)務(wù))。
如康威定律所說(shuō):
Organizations which design systems[…] are constrained to produce designs which are copies of the communication structures of these organizations.
設(shè)計(jì)系統(tǒng)的組織,其產(chǎn)生的設(shè)計(jì)和架構(gòu)等價(jià)于組織間的溝通結(jié)構(gòu)。
單體架構(gòu)到微服務(wù)架構(gòu)是這個(gè)定律很好的體現(xiàn)。直播業(yè)務(wù)從一開(kāi)始劃分了三個(gè)大的macro service domain,分別是用戶(hù)、主播、營(yíng)收。房間服務(wù)被劃分在了主播這個(gè)Domain內(nèi),因其是主播創(chuàng)建房間、開(kāi)播推流的基礎(chǔ)載體,沒(méi)有直播內(nèi)容供給整個(gè)直播業(yè)務(wù)都無(wú)從談起。
將單塊架構(gòu)先解耦成三塊大的業(yè)務(wù)域,每個(gè)團(tuán)隊(duì)開(kāi)發(fā),測(cè)試和發(fā)布自己負(fù)責(zé)的服務(wù),互不干擾,系統(tǒng)效率得到提升,滿(mǎn)足了一個(gè)階段內(nèi)業(yè)務(wù)快速發(fā)展對(duì)于技術(shù)的要求。
本文后續(xù)將主播域(關(guān)注內(nèi)容生產(chǎn))簡(jiǎn)稱(chēng)為B端,將用戶(hù)域(關(guān)注流量消費(fèi))簡(jiǎn)稱(chēng)為C端,方便理解。
現(xiàn)狀分析
大單體應(yīng)用拆分之初,房間服務(wù)是從中拆出的單個(gè)PHP服務(wù)room-service,不過(guò)服務(wù)中仍然耦合了過(guò)多的業(yè)務(wù)邏輯,從業(yè)務(wù)重要性/讀寫(xiě)輕重/前后臺(tái)區(qū)分/面向用戶(hù)區(qū)分等幾個(gè)角度上考慮都不應(yīng)該繼續(xù)在這個(gè)服務(wù)中繼續(xù)迭代業(yè)務(wù)邏輯。
隨著B(niǎo)站Golang微服務(wù)化演進(jìn),從room服務(wù)中陸續(xù)拆分出了幾個(gè)新的微服務(wù):
- xroom/daoanchor:房間主體服務(wù)
- xanchor:主播業(yè)務(wù)服務(wù)
- xroom-management:房間管控服務(wù)
- xroom-extend:房間擴(kuò)展信息服務(wù)
從組織視角拆分是合理有效的,但是從技術(shù)視角去觀(guān)察,房間服務(wù)既需要滿(mǎn)足B端開(kāi)播場(chǎng)景的數(shù)據(jù)強(qiáng)一致性要求,也需要承擔(dān)來(lái)自C端用戶(hù)“推薦頁(yè)”、“上下滑列表頁(yè)”、“進(jìn)房”等業(yè)務(wù)場(chǎng)景的高QPS。
xroom作為底層服務(wù),常態(tài)化晚高峰需要承擔(dān)35W+ QPS,單接口最大QPS 18W,大流量Query通過(guò)服務(wù)熱點(diǎn)主動(dòng)探測(cè)+Local Cache+依賴(lài)緩存組件抗壓,Redis主集群QPS達(dá)到百萬(wàn)級(jí)別,盡量去減少DB層面回源的請(qǐng)求量級(jí)。
房間讀多活架構(gòu)和多級(jí)緩存方案實(shí)施后,又需要一些措施能夠去主動(dòng)探測(cè)發(fā)現(xiàn)偶發(fā)的數(shù)據(jù)不一致問(wèn)題。
房間服務(wù)時(shí)常需要應(yīng)對(duì)保障“關(guān)鍵事件開(kāi)播管控”和“高熱賽事直播”兩種不同的業(yè)務(wù)場(chǎng)景,前者更關(guān)注房間開(kāi)播平穩(wěn)管控及時(shí)有效,后者關(guān)注高流量用戶(hù)進(jìn)房,技術(shù)服務(wù)上的降級(jí)緩存/兜底邏輯/熔斷策略也會(huì)有差異。
If the same data model is not able to satisfy the read and write patterns of a system effectively, then it makes sense to decouple the two schemas by applying CQRS.
如果同一個(gè)數(shù)據(jù)模型不能有效滿(mǎn)足系統(tǒng)的讀寫(xiě)模式,那么通過(guò)應(yīng)用CQRS來(lái)解耦這兩個(gè)架構(gòu)是有意義的。
通過(guò)CQRS我們可以切實(shí)分離大流量的讀場(chǎng)景和注重實(shí)時(shí)性和一致性的多寫(xiě)場(chǎng)景。尤其對(duì)于C端大流量來(lái)說(shuō),可以無(wú)狀態(tài)擴(kuò)容服務(wù)節(jié)點(diǎn)。理論上可以達(dá)到無(wú)限擴(kuò)展目標(biāo),這對(duì)于千萬(wàn)在線(xiàn)的直播是尤其重要的。
The second scenario in which CQRS is helpful is in separating the read load from the write load.
第二種 CQRS 有用的情況是將讀取負(fù)載與寫(xiě)入負(fù)載分開(kāi)。
CQRS架構(gòu)模式適用性
主播是房間的所有者,對(duì)房間有管理權(quán)力,能夠改變直播間的狀態(tài)與屬性。
觀(guān)看用戶(hù)則是房間內(nèi)容的消費(fèi)者,B和C視角下都會(huì)有一個(gè)叫做“房間”的內(nèi)容承載體。從面向用戶(hù)和權(quán)責(zé)分離角度來(lái)說(shuō),CQRS是比較好的一種思想來(lái)指導(dǎo)房間服務(wù)體系和業(yè)務(wù)域的拆分演進(jìn)。
拆分目的是減少B端和C端之間領(lǐng)域穿插,雙方更加聚焦各自的業(yè)務(wù)領(lǐng)域,最終閉環(huán)從而提升架構(gòu)穩(wěn)定性規(guī)避系統(tǒng)性風(fēng)險(xiǎn),并提升各自業(yè)務(wù)域內(nèi)的組織效率。
業(yè)務(wù)拆分共識(shí)
圍繞房間實(shí)體,業(yè)務(wù)上有生產(chǎn)和消費(fèi)的邏輯需要盤(pán)點(diǎn),從BFF/基礎(chǔ)房間服務(wù)/直播biz服務(wù)三層進(jìn)行BC Domain的拆分。
- B/C兩端,都具有完整業(yè)務(wù)領(lǐng)域,領(lǐng)域內(nèi)有各自相對(duì)獨(dú)立的業(yè)務(wù)上下文
- App客戶(hù)端/Web前端,屬于多個(gè)領(lǐng)域共用的“視窗”
- C端有兩路數(shù)據(jù)流,一路是看端領(lǐng)域閉環(huán)的數(shù)據(jù)流,第二路數(shù)據(jù)流是B端的數(shù)據(jù)流(開(kāi)關(guān)播上下文、房間狀態(tài)變化上下文)
圖片
根據(jù)GRASP(General Responsibility Assignment Software Pattern)中的信息專(zhuān)家(Information Expert)模式,數(shù)據(jù)應(yīng)該放在需要經(jīng)常使用它的地方,同時(shí)某一個(gè)功能在哪里實(shí)現(xiàn),取決于數(shù)據(jù)哪里。換句話(huà)講,數(shù)據(jù)+功能=領(lǐng)域。
架構(gòu)演進(jìn)目標(biāo)
房間核心系統(tǒng)耦合了消費(fèi)端和生產(chǎn)端的邏輯,基于CQRS理論需要將服務(wù)和數(shù)據(jù)庫(kù)完全解耦,承擔(dān)高流量的xroom/dananchor服務(wù)劃分為C端業(yè)務(wù)域服務(wù),新的B端服務(wù)閉環(huán)接受內(nèi)容生產(chǎn)的讀寫(xiě)請(qǐng)求和后臺(tái)管控聚合請(qǐng)求(寫(xiě)多讀少)。
B端核心房間數(shù)據(jù)變更通過(guò)領(lǐng)域事件消息通知給到C端,C端關(guān)注數(shù)據(jù)的最終一致性,期間會(huì)有數(shù)據(jù)對(duì)賬腳本主動(dòng)發(fā)現(xiàn)數(shù)據(jù)不一致并自動(dòng)修復(fù)。
總體方向按照C&B職能原則來(lái)拆分,過(guò)渡階段允許歷史請(qǐng)求寫(xiě)請(qǐng)求C服務(wù),C proxy to B service。
圖片
最終目標(biāo)是完全解耦,通過(guò)領(lǐng)域事件數(shù)據(jù)流來(lái)同步必要信息。
圖片
沒(méi)有銀彈
我們享受到了CQRS帶來(lái)的便利,相反的也要解決引入它帶來(lái)的“副作用”,這些副作用在直播領(lǐng)域下,表現(xiàn)的最核心無(wú)疑是開(kāi)關(guān)播狀態(tài)的延遲,但是由于用戶(hù)和主播的天然隔離,反而不需要兩邊完全實(shí)時(shí)。
主播開(kāi)播后,需要推流等一些列的動(dòng)作,直到用戶(hù)可以看到主播的直播畫(huà)面,這個(gè)過(guò)程中很自然,符合人的直覺(jué),而在架構(gòu)層面我們通過(guò)引入消息中間件來(lái)同步數(shù)據(jù),本身耗時(shí)在毫秒級(jí)別,這相比前面的自然過(guò)程幾乎可以忽略,但是我們的技術(shù)架構(gòu)上服務(wù)和數(shù)據(jù)完全拆開(kāi)了。
同時(shí)因?yàn)橐肓烁嗟臄?shù)據(jù)交互環(huán)節(jié),請(qǐng)求拓?fù)渥兊酶訌?fù)雜,每個(gè)環(huán)節(jié)的數(shù)據(jù)正確性排查變得更困難。我們通過(guò)平臺(tái)提供的Tracing+Metrics+Logging來(lái)進(jìn)行問(wèn)題輔助定位,雙寫(xiě)+對(duì)賬腳本保障過(guò)渡階段數(shù)據(jù)最終一致性,灰度階段控制讀寫(xiě)流量各自單獨(dú)放量驗(yàn)證。
為了應(yīng)對(duì)CQRS架構(gòu)帶來(lái)的復(fù)雜性確實(shí)需要額外引入數(shù)據(jù)服務(wù)腳本等方式去做保障,這部分的思路更偏向于架構(gòu)設(shè)計(jì)中的“風(fēng)險(xiǎn)驅(qū)動(dòng)”。
執(zhí)行落地過(guò)程
對(duì)于當(dāng)前比較成熟的業(yè)務(wù)系統(tǒng)去做拆分,是一件比較有挑戰(zhàn)的事情。我們先從橫縱兩個(gè)角度看下房間服務(wù)所在的層級(jí)位置。
橫向技術(shù)架構(gòu)分層
- 面向用戶(hù)的終端設(shè)備:App粉版、Web端、開(kāi)播App等
- CDN -> SLB -> APIGW:內(nèi)容分發(fā)邊緣加速,LB層與統(tǒng)一網(wǎng)關(guān)
- BFF:Backend for Frontend,根據(jù)終端渠道區(qū)分的業(yè)務(wù)網(wǎng)關(guān)入口,eg:app-room / web-room / app-interface
- Biz Service:業(yè)務(wù)邏輯服務(wù)
- Domain Service / Fundamental Service:業(yè)務(wù)域服務(wù)/基礎(chǔ)服務(wù),eg:Room Domain Service / Account Service
縱向部署隔離
- Region:eg sh/bj
- Zone:eg sh001/sh002/sh003,每個(gè)Zone單元內(nèi)的流量應(yīng)盡可能閉環(huán)(讀多活寫(xiě)回源 -> 讀寫(xiě)多活、BFF failback cross Zone可選策略)
- Cluster/Group:group1/group2/染色group,不同group可以設(shè)置服務(wù)發(fā)線(xiàn)上的weight權(quán)重
- AppID:每個(gè)應(yīng)用的服務(wù)發(fā)現(xiàn)naming id
圖片
可以看到房間服務(wù)有眾多的請(qǐng)求上游,必須在讀寫(xiě)切分過(guò)程中,保障好數(shù)據(jù)的一致性(B端業(yè)務(wù)域內(nèi)強(qiáng)一致性,C端業(yè)務(wù)域內(nèi)最終一致性)和服務(wù)的可用性(底層服務(wù)抖動(dòng)會(huì)有放大效應(yīng))。
當(dāng)然,上游業(yè)務(wù)服務(wù)fanout過(guò)多讀流量到下游服務(wù)也是需要治理的,這在另一個(gè)議題中去開(kāi)展了。
在具體的實(shí)現(xiàn)過(guò)程中,我們將整個(gè)拆分劃分成三大階段。
圖片
- 數(shù)據(jù)對(duì)齊階段
本階段目標(biāo)是把B端的數(shù)據(jù)庫(kù)從C端復(fù)制,并且保持?jǐn)?shù)據(jù)一致。并且此階段可以拆分成增量對(duì)齊階段和存量對(duì)齊階段。
增量對(duì)齊,將新數(shù)據(jù)的創(chuàng)建和更新通過(guò)雙寫(xiě)同步。
存量對(duì)齊,通過(guò)同步JOB將C端DB的存量數(shù)據(jù)同步到B端新DB,并且需要一種對(duì)賬系統(tǒng)去針對(duì)全量數(shù)據(jù)進(jìn)行周期性的對(duì)比,來(lái)確保數(shù)據(jù)一致性。
- 數(shù)據(jù)同步階段
針對(duì)數(shù)據(jù)一致性問(wèn)題和業(yè)務(wù)上數(shù)據(jù)實(shí)時(shí)性問(wèn)題,需要對(duì)相應(yīng)的實(shí)時(shí)場(chǎng)景進(jìn)行改造。B端構(gòu)建新的房間領(lǐng)域事件消息,并同步到C端。
此階段完成C&B分寫(xiě)邏輯,通過(guò)在DAO層控制BC表級(jí)和字段級(jí)的寫(xiě)入控制,將寫(xiě)操作分流到B和C的各自服務(wù)內(nèi),并且通過(guò)消息事件,來(lái)同步數(shù)據(jù)變更。此階段完成了數(shù)據(jù)拆分和同步的目標(biāo)。
If the choice is made to keep the updates asynchronous, the entire system is forced to deal with the fallout of eventual consistency.
如果選擇保持更新為異步的,整個(gè)系統(tǒng)將不得不處理最終一致性所帶來(lái)的后果。
- 最終閉環(huán)階段
此階段作為收尾,我們將上游的調(diào)用梳理出來(lái),并且改造讀取各自領(lǐng)域真正的依賴(lài)服務(wù),最終達(dá)到完全解耦的目標(biāo)。
核心設(shè)計(jì)
數(shù)據(jù)拆分 Data Division
當(dāng)前直播的核心實(shí)體數(shù)據(jù)庫(kù),BC屬于公用的狀態(tài),每張表和每個(gè)字端按照上述的原則是可以劃分出BC屬性的。所以我們一步到位,顆粒度到最小單位字段級(jí)別,確保完全解耦。
BC拆分后短時(shí)間內(nèi)兩套獨(dú)立數(shù)據(jù)庫(kù)的表字段可以保持相同,長(zhǎng)期根據(jù)業(yè)務(wù)迭代節(jié)奏不同,兩邊可以變?yōu)楫悩?gòu)shcema模式。同時(shí)要注意的是,業(yè)務(wù)數(shù)據(jù)層面切分后,需要聯(lián)動(dòng)大數(shù)據(jù)層面同步hive表的變更,單獨(dú)重新建?;驍?shù)據(jù)任務(wù)換源,這點(diǎn)是比較容易遺漏的。
領(lǐng)域事件驅(qū)動(dòng) Domain Event-Driven
BC房間業(yè)務(wù)各自劃分業(yè)務(wù)域邊界后,域之間的數(shù)據(jù)同步應(yīng)通過(guò)領(lǐng)域事件驅(qū)動(dòng)+觀(guān)察者模式去實(shí)現(xiàn);域內(nèi)的核心業(yè)務(wù)邏輯,可以走應(yīng)用服務(wù)編排。
本次實(shí)踐過(guò)程中重新梳理制定了“房間狀態(tài)變更”事件,basic room info + extra info,滿(mǎn)足訂閱者服務(wù)對(duì)房間業(yè)務(wù)域核心字段的要求。
跨微服務(wù)的事件機(jī)制要總體考慮事件構(gòu)建、發(fā)布和訂閱、事件數(shù)據(jù)持久化、消息中間件,甚至事件數(shù)據(jù)持久化時(shí)還可能需要考慮引入分布式事務(wù)機(jī)制等。完整實(shí)踐下來(lái)還是成本還是比較高的,實(shí)施者應(yīng)考慮結(jié)合業(yè)務(wù)場(chǎng)景和對(duì)數(shù)據(jù)的實(shí)時(shí)性/一致性要求來(lái)決定實(shí)踐到哪一步。
Tip1:訂閱者需要實(shí)現(xiàn)消費(fèi)冪等,業(yè)務(wù)場(chǎng)景如果有訴求需要額外實(shí)現(xiàn)數(shù)據(jù)版本協(xié)議(eg:稿件系統(tǒng)BC CQRS拆分,B端稿件數(shù)據(jù)被重新編輯審核,C端已開(kāi)放的版本仍然可以瀏覽,即使用了數(shù)據(jù)版本協(xié)議字段)。
Tip2:如果訂閱者有實(shí)現(xiàn)接收Message后反向callback query的模式(更適合去保障最終一致性),需要關(guān)注query的數(shù)據(jù)源是來(lái)自主庫(kù)or從庫(kù),不然會(huì)有因主從同步時(shí)延導(dǎo)致的數(shù)據(jù)不一致case。
Tip3:絕對(duì)不要將核心DB的binlog消息暴露為Domain Message,一是暴露了過(guò)多細(xì)節(jié)字段下游并不一定都需要訂閱關(guān)心,要做很多filter邏輯,二是核心DB的字段變更將需要牽動(dòng)所有下游,不利于變更。
灰度控制 Gray Scale Control
核心服務(wù)變更依賴(lài)一個(gè)比較完備的灰度發(fā)布方案,基于分布式KV組件(服務(wù)可以近實(shí)時(shí)地獲取到KV系統(tǒng)中配置的開(kāi)關(guān)變更)我們?cè)O(shè)計(jì)了從BFF網(wǎng)關(guān)到服務(wù)的開(kāi)關(guān),來(lái)控制字段的外顯和關(guān)鍵Topic發(fā)送。
灰度策略有:功能總體關(guān)閉、白名單模式放量、百分位/千分位放量、功能全量打開(kāi),服務(wù)發(fā)布觀(guān)察遵從這個(gè)流程,從APIGW+服務(wù)染色發(fā)布引入流量+功能KV開(kāi)關(guān)做到謹(jǐn)慎放量。
可觀(guān)測(cè)性建設(shè) Observability Construction
新的架構(gòu)落地只是起點(diǎn),真正的考驗(yàn)剛剛開(kāi)始。我們必須為架構(gòu)的穩(wěn)定性,可用性負(fù)責(zé)。
保障整個(gè)CQRS系統(tǒng),需要“配套設(shè)施”,其中的首要利器就是做可觀(guān)測(cè)性建設(shè)(Observability Construction),基于現(xiàn)有的基架能力,我們搭建了直播CQRS監(jiān)控大盤(pán),從生產(chǎn)方到消費(fèi)方,全鏈路監(jiān)控核心指標(biāo)。
其中CQRS中的數(shù)據(jù)同步的相關(guān)指標(biāo),在數(shù)據(jù)保證數(shù)據(jù)最終一致性的背景下,尤其重要。整個(gè)實(shí)時(shí)性由三個(gè)部分組成,pub時(shí)間,網(wǎng)絡(luò)傳輸耗時(shí),sub處理數(shù)據(jù),其中在我們的CQRS大盤(pán)中,就包含B端業(yè)務(wù)pub的時(shí)間監(jiān)控,和C端sub業(yè)務(wù)處理的時(shí)間監(jiān)控,目前網(wǎng)絡(luò)傳輸耗時(shí)在毫秒級(jí)別,并且這塊指標(biāo)也已經(jīng)在灰度階段。
圖片
系統(tǒng)魯棒性 System Robustness
CQRS的引入幫我們解耦了截然不同兩種場(chǎng)景的系統(tǒng),但是也確實(shí)引入了mq,從全局視角看又增加了一個(gè)依賴(lài),所以系統(tǒng)的復(fù)雜度是增加的。為了增強(qiáng)系統(tǒng)架構(gòu)的魯棒性,我們考慮到引入另外一種備選手段來(lái)做數(shù)據(jù)同步,通過(guò)直連服務(wù)接口調(diào)用的方式,這塊我們使用了我站自研的railgun消息處理組件。當(dāng)兩種本身可用性就很高的方法互為補(bǔ)充時(shí),那么出現(xiàn)問(wèn)題的可能,相當(dāng)于兩個(gè)系統(tǒng)同時(shí)出問(wèn)題的概率,這種概率是極低的。
在整個(gè)CQRS數(shù)據(jù)鏈路上,我們還針對(duì)一些寫(xiě)場(chǎng)景做了異步重試來(lái)系統(tǒng)自愈,抵抗服務(wù)可用性的長(zhǎng)尾不可用,另外我們也考慮到異常場(chǎng)景下,雖然降級(jí)到http調(diào)用同步數(shù)據(jù),但是存量消息恢復(fù)時(shí),數(shù)據(jù)不是最新的,所以加入過(guò)時(shí)消息走回源,保障數(shù)據(jù)正確性的設(shè)計(jì),來(lái)盡可能讓系統(tǒng)在各個(gè)環(huán)節(jié)的抗風(fēng)險(xiǎn)能力提升。
數(shù)據(jù)對(duì)賬腳本 Data Verify Job
有一種比較常見(jiàn)的方式,即流式對(duì)賬,依靠我們數(shù)據(jù)流監(jiān)控組件去實(shí)現(xiàn),在設(shè)定一個(gè)經(jīng)驗(yàn)值的時(shí)間窗口閾值內(nèi),對(duì)兩邊數(shù)據(jù)源的流式binlog做對(duì)比。這種對(duì)賬方式比較適合終態(tài)業(yè)務(wù)對(duì)賬,而我們實(shí)時(shí)直播屬于反復(fù)跳變場(chǎng)景,目前我們利用最簡(jiǎn)單有效的方式,連接雙方從庫(kù),以B端庫(kù)為準(zhǔn)進(jìn)行數(shù)據(jù)對(duì)賬,并且滿(mǎn)足30s內(nèi)數(shù)據(jù)一致比較,來(lái)兼容數(shù)據(jù)最終一致性,當(dāng)對(duì)賬腳本發(fā)現(xiàn)不一致后,通過(guò)日志+主動(dòng)告警+機(jī)器人等手段,配合自動(dòng)化修復(fù)任務(wù)做自愈的設(shè)計(jì),從而cover住大多數(shù)異常case,做到平常0職守。
線(xiàn)上事故響應(yīng)SOP Incident Response SOP
上文的系統(tǒng)魯棒性設(shè)計(jì),最大程度保障服務(wù)的健壯穩(wěn)定,以及上文兜底的數(shù)據(jù)對(duì)賬機(jī)制,最大程度客觀(guān)地幫助系統(tǒng)發(fā)現(xiàn)異常,而線(xiàn)上永遠(yuǎn)有我們意想不到的情況,所以我們?cè)O(shè)計(jì)了一套線(xiàn)上事故響應(yīng)機(jī)制,來(lái)應(yīng)對(duì)“意外”。
首先我們從CQRS和BC服務(wù)的角度,預(yù)設(shè)配置了不同領(lǐng)域的關(guān)鍵日志或者指標(biāo)告警,而且劃分了不同的緊急程度。二是我們提前管理規(guī)劃了告警組成員,覆蓋兩邊領(lǐng)域的一線(xiàn)研發(fā),并且配置不同的通知渠道,可以讓最合適的同學(xué)最快地感知異常。三是我們從不同角度預(yù)設(shè)了我們可以枚舉異常現(xiàn)象,再去枚舉不同現(xiàn)象發(fā)生的根因,再輸出可以解決的方案list,所以基于這套sop,配合我站alchemy平臺(tái)tracing鏈路追蹤能力可以迅速定位故障點(diǎn),以最快速度執(zhí)行預(yù)設(shè)標(biāo)準(zhǔn)步驟,達(dá)到最快恢復(fù)可用性的目的。
生產(chǎn)配套 Production Support
一個(gè)安全的生產(chǎn)系統(tǒng)是需要一整套的“生產(chǎn)配套”體系,可以快速定位排障。這塊我們借鑒了很多類(lèi)似系統(tǒng),參考了醫(yī)院體系的”問(wèn)診臺(tái)“,目前發(fā)育出開(kāi)播互動(dòng)問(wèn)診臺(tái)生產(chǎn)配套,提升問(wèn)題排障效率幾乎80%。
圖片
技術(shù)項(xiàng)目管理
最后想聊聊技術(shù)項(xiàng)目的價(jià)值和實(shí)施周期。技術(shù)項(xiàng)目有些時(shí)候由于不會(huì)帶來(lái)明顯的業(yè)務(wù)增量?jī)r(jià)值,往往會(huì)被質(zhì)問(wèn)“為什么要做如此變更,不做這個(gè)變更業(yè)務(wù)難道不能用嗎?”諸如此類(lèi)的靈魂拷問(wèn)。
每個(gè)階段技術(shù)建設(shè)需要有一條經(jīng)過(guò)設(shè)計(jì)的baseline,這條線(xiàn)應(yīng)該略快于業(yè)務(wù)發(fā)展的基線(xiàn)一步。建設(shè)落后,技術(shù)跟不上業(yè)務(wù),如同沙地之上建高樓,業(yè)務(wù)連續(xù)性會(huì)受到技術(shù)系統(tǒng)穩(wěn)定性可用性的lost而直接受損。
建設(shè)過(guò)快,又有Over Design/Over Engineering的問(wèn)題,所以略快過(guò)一步是合適的,保留了彈性擴(kuò)展的余地,可以在需要時(shí)適配業(yè)務(wù)快速調(diào)整。
架構(gòu)師和Tech Leader需要協(xié)同階段性review當(dāng)前技術(shù)建設(shè)baseline和業(yè)務(wù)的適配情況,并決定是否投入有效資源進(jìn)行技術(shù)架構(gòu)迭代。
技術(shù)項(xiàng)目從立項(xiàng)之日起,就需要更嚴(yán)格于業(yè)務(wù)項(xiàng)目的管理機(jī)制。業(yè)務(wù)項(xiàng)目的業(yè)務(wù)目標(biāo)(試錯(cuò)/AB實(shí)驗(yàn)/明確性收益延展)往往不由工程師來(lái)制定,而技術(shù)項(xiàng)目的目標(biāo)感也是需要從開(kāi)始就建立起來(lái)的,這有助于關(guān)鍵行為路徑拆解,并在項(xiàng)目收尾階段進(jìn)行目標(biāo)&結(jié)果比對(duì)。
技術(shù)項(xiàng)目要有階段性Milestone管理,技術(shù)立項(xiàng) -> (原型方案討論) -> 技術(shù)方案確定 -> 技術(shù)實(shí)施(大項(xiàng)目應(yīng)分階段實(shí)施,過(guò)程指標(biāo)也被Track) -> 測(cè)試/驗(yàn)證方案(測(cè)試用例收集&review) -> 發(fā)布方案 -> 線(xiàn)上驗(yàn)收方案 -> (線(xiàn)上問(wèn)題處理預(yù)案) -> 項(xiàng)目結(jié)果復(fù)盤(pán)。
立項(xiàng)、技術(shù)方案確認(rèn)等階段需要有正式官宣(儀式感/目標(biāo)感/參與感),避免流于私下的技術(shù)Topic探討,導(dǎo)致無(wú)法被正式地投入資源到實(shí)施階段。
End
最后,該項(xiàng)目實(shí)踐上仍然有諸多細(xì)節(jié)無(wú)法在文章中一一展示,文本在撰寫(xiě)過(guò)程中也難免犯錯(cuò),希望大家可以指正,歡迎大家可以一起來(lái)進(jìn)行技術(shù)交流。
參考
- https://learn.microsoft.com/en-us/azure/architecture/patterns/cqrs
- https://kislayverma.com/software-architecture/architecture-pattern-cqrs/?fileGuid=0IWvR8dLbi0m7fi4
- https://en.wikipedia.org/wiki/GRASP_(object-oriented_design)
本期作者
劉瑞洲嗶哩嗶哩資深開(kāi)發(fā)工程師
王清培 嗶哩嗶哩資深開(kāi)發(fā)工程師