當前疫情下火爆的直播應(yīng)用,你了解背后的技術(shù)架構(gòu)嗎?
這場疫情讓線下零售降至冰點,但是卻帶火了直播應(yīng)用。直播電商、直播教育等各類直播應(yīng)用可謂贏得了歷史性的機會,很多大眾開始接受并認可這種新型應(yīng)用的便利和價值,個人感覺隨著5G的普及,『直播+垂直領(lǐng)域+精細化的私域流量』將會是互聯(lián)網(wǎng)的一個大熱點,迎來真正的紅利期。
直播行業(yè)大概在10年多前就開始興起了,秀場直播和游戲直播是PC時代比較成功的應(yīng)用場景,直到16年,隨著移動互聯(lián)網(wǎng)的大規(guī)模普及,直播行業(yè)迎來了真正的元年,成百上千的直播APP出現(xiàn)在大眾視野,大概在18年年初,直播答題當時火了一把,那算是直播類應(yīng)用的第一次全民普及,然后是19年短視頻網(wǎng)站掀起的直播電商?;仡欀辈バ袠I(yè)的發(fā)展歷程,直播類應(yīng)用在各個領(lǐng)域遍地開花,那么它背后的技術(shù)架構(gòu)你是否了解?
兩年前,我參與了一個支持100萬用戶同時在線、20萬并發(fā)的直播答題系統(tǒng)的架構(gòu)設(shè)計,下文將以『直播答題』的應(yīng)用場景為例,帶你了解當前疫情下火爆的直播應(yīng)用背后的技術(shù)架構(gòu)。內(nèi)容分成以下4個部分:
- 產(chǎn)品功能簡介
- 面臨的技術(shù)挑戰(zhàn)
- 技術(shù)選型及依據(jù)
- 架構(gòu)設(shè)計方案
01 產(chǎn)品功能簡介
直播答題能在當時成為風口,得益于它的玩法足夠簡單,用戶教育成本幾乎為0。簡單來說就是:全民在線PK、10秒答題、超時或答錯即退出游戲、成功答對所有題即可平分獎金,俗稱在線版的開心辭典。
在了解系統(tǒng)設(shè)計方案和架構(gòu)之前,先看看直播答題應(yīng)用有哪些核心功能?下面是APP端的幾張產(chǎn)品截圖:
1、答題以活動的形式展開,每場活動都會預(yù)先公布直播開始時間、答題總獎金、紅包雨獎金等信息。
2、活動時間到后,用戶就可以進入直播間,看到實時的視頻流,有專業(yè)的主持人進行串詞口播,場控人員會配合主持人同步進行發(fā)題、公布答案等操作。
3、題目下發(fā)后,用戶有10秒的作答時間,答錯或者超時即退出游戲,如果用戶有復(fù)活道具在答錯時會自動使用,用戶能繼續(xù)進行答題。
4、為了留住答錯用戶,活動期間有多場紅包雨,用戶點擊屏幕就有概率搶到。
5、活動期間用戶可發(fā)彈幕,同時會有彈幕滾屏輪播,以營造熱鬧的直播氛圍。
6、其他功能:邀請新人、活動榜單、獎金提現(xiàn)等。
其他直播類應(yīng)用在產(chǎn)品功能上和直播答題類似,基本也是這兩類:
1、直播的基礎(chǔ)功能:連麥互動直播(支持多碼率、多協(xié)議,多主播同框)、美顏特效、彈幕、IM聊天、點贊、屏幕共享等功能性需求,以及防盜鏈、涉黃涉政鑒別等非功能性需求。
2、應(yīng)用本身的個性化功能:比如答題場景中的發(fā)題目、作答、公布答案,電商場景中的商品展示、一鍵下單購買,網(wǎng)紅直播場景中的禮物打賞。
02 面臨的技術(shù)挑戰(zhàn)
當時我們做直播答題應(yīng)用時,面臨以下技術(shù)挑戰(zhàn):
1、音視頻處理及傳輸:涉及音視頻編碼、實時美顏、視頻推流、CDN加速分發(fā)、終端適配和播放,流量統(tǒng)計等諸多技術(shù)點,而且我們當時的技術(shù)團隊沒有專門做音視頻方面的專家。
2、高并發(fā)請求:參考了沖頂大會等答題競品的用戶量級,預(yù)計會有100W用戶同時在線,1秒內(nèi)有20W用戶同時答題;1秒內(nèi)單個用戶可觸屏發(fā)起4-5次搶紅包請求,并發(fā)最大可達到500W QPS.
3、高帶寬壓力:按照標清視頻的標準,觀看直播的碼流至少為1Mbps,如果100W用戶在線,光視頻流的出口帶寬能達到976.56G bps。1條彈幕可達到130字節(jié),1秒要滾屏20條彈幕,如果需要同時推送給100W用戶,彈幕的出口帶寬也將達到19.37G bps.
4、高計算壓力:1道題目的對錯判斷涉及到答案比對、復(fù)活道具的使用、判斷用戶是否創(chuàng)了新紀錄,同時還涉及一系列的反作弊策略(比如前面的題目答錯了將無法繼續(xù)作答),在主持人口播公布答案的瞬間,如何快速完成100W用戶的答題結(jié)果計算?
5、資金流的正確性和安全性:單個用戶最多搶3個紅包如何不多領(lǐng)?財務(wù)上如何保證答題獎金、紅包獎勵不出現(xiàn)1分錢的誤差?
6、低延遲性要求:直播場景下如何整合視頻流和業(yè)務(wù)數(shù)據(jù)流,做到聲音、主播畫面和題目同步,以保證用戶體驗?
7、對商城交易業(yè)務(wù)的低干擾:直播答題僅作為商城的一個運營活動,核心目標是導(dǎo)流,它依托商城原有的用戶體系,運營系統(tǒng),大數(shù)據(jù)系統(tǒng),提現(xiàn)通道等,如何做到對商城現(xiàn)有交易系統(tǒng)的低干擾?
可見答題這種泛娛樂的直播場景還是有挺多技術(shù)挑戰(zhàn)的,它取決于直播應(yīng)用的用戶量級和業(yè)務(wù)流程。就算是直播電商這種低頻交易轉(zhuǎn)化的場景,要是李佳琪在帶貨,同樣也會面臨瞬時搶購的高并發(fā)挑戰(zhàn),所以架構(gòu)設(shè)計時必須考慮業(yè)務(wù)最高峰時的壓力,并且系統(tǒng)的各個環(huán)節(jié)必須具備動態(tài)可伸縮的能力。
03 技術(shù)選型及依據(jù)
一. 音視頻處理及傳輸?shù)姆桨高x型
音視頻處理及傳輸,因為技術(shù)團隊不具備這方面的能力,所以當時調(diào)研了各種云廠商的付費解決方案,最終采用了騰訊云的直播解決方案。主持人側(cè):通過演播室的專業(yè)攝像設(shè)備,搭載騰訊云提供的obs推流軟件,即可進行視頻錄制和推流。用戶側(cè):APP端集成騰訊云的SDK,動態(tài)拿到推流地址后即可觀看直播。
二. 業(yè)務(wù)數(shù)據(jù)流的方案選型
業(yè)務(wù)數(shù)據(jù)是指除音視頻以外的,和答題應(yīng)用場景相關(guān)的數(shù)據(jù)(比如題目、答案、彈幕、紅包等)。騰訊云提供了兩種可選方案:
1、題目預(yù)先設(shè)置好,直接由騰訊云的SDK通過音視頻通道下發(fā),打入直播流中。
2、讓題目先通過騰訊云的IM通道快速送達觀眾端APP,在觀眾端先緩存下來,等待播放器通知了預(yù)期的 NTP 時間戳之后,再把題目顯示出來。
騰訊云的這兩種方案都可以提供“音-畫-題”的完美同步,但是存在以下局限:用戶的答案必須以HTTP請求方式匯總到答題服務(wù)器,這一塊必須自己開發(fā),另外公布答案、搶紅包、彈幕這些業(yè)務(wù)騰訊云系統(tǒng)都是不支持的,在底層通信通道上仍然需要自行開發(fā)。
考慮上述局限以及業(yè)務(wù)的多變性,我們最終打算自研業(yè)務(wù)數(shù)據(jù)流通道。這樣視頻流和業(yè)務(wù)數(shù)據(jù)流會分兩個通道下發(fā),因為業(yè)務(wù)流相對視頻流的數(shù)據(jù)量很小,只要能保證業(yè)務(wù)邏輯的處理速度和業(yè)務(wù)數(shù)據(jù)的下行速度,“音-畫-題”的延遲是可以接受的。畢竟當時已經(jīng)是4G時代,如果用戶側(cè)的網(wǎng)速不行,視頻流可能都無法正常觀看了。
為了做到業(yè)務(wù)數(shù)據(jù)流的獨立傳輸,需要實現(xiàn)一個長連接、高性能的網(wǎng)關(guān)服務(wù)器(支持100W用戶同時在線,20W并發(fā)答題,彈幕實時推送等要求),我們的技術(shù)選型是:Netty、ProtoBuf、WebSocket,選型理由:
1、Netty:Netty是當時最流行的高性能和異步NIO框架,直播答題的業(yè)務(wù)場景中,涉及到題目下發(fā)、彈幕、下紅包雨等非常多的推送場景,而且一場答題活動中,客戶端和服務(wù)端的通信頻繁,長連接比短連接在性能上更優(yōu)。
2、ProtoBuf:作為客戶端和服務(wù)端的數(shù)據(jù)交換格式,PB是一種效率和兼容性都很優(yōu)秀的二進制數(shù)據(jù)傳輸格式,在碼流和序列化速度上明顯優(yōu)于JSON、XML、hessian等主流格式,同時支持向前向后兼容以及各種主流語言。
3、WebSocket:是 HTML5 一種新的協(xié)議,用來實現(xiàn)客戶端與服務(wù)器端的長連接通訊。
三. 服務(wù)端的部署方案選型
前面提過,直播答題僅作為商城的一個運營活動,它依托商城原有的用戶體系,運營系統(tǒng),大數(shù)據(jù)系統(tǒng),提現(xiàn)通道等。現(xiàn)有的商城系統(tǒng)部署在我們自建的機房中,為了降低對商城現(xiàn)有交易系統(tǒng)的低干擾,我們采用了『私有云+公有云』的混合部署方案。將高并發(fā)的答題系統(tǒng)以及它所依賴的緩存、MQ等公共組件部署在公有云上,方便彈性擴展,同時降低對商城交易系統(tǒng)的流量沖擊。
04 架構(gòu)設(shè)計方案
一. 音視頻直播架構(gòu)
上面是騰訊云直播解決方案的架構(gòu)圖,其他云廠商(比如阿里云)的直播解決方案,技術(shù)架構(gòu)類似。感興趣的同學可以直接去騰訊云官網(wǎng)上詳細了解,這里不做展開。
二. 數(shù)據(jù)流方案
音視頻流采用了騰訊云的直播解決方案,而業(yè)務(wù)數(shù)據(jù)流(活動、題目、答案、彈幕、紅包等)則采用了自研的長連接方案。架構(gòu)圖中的答題系統(tǒng)和答題運營后臺也均為自研??蛻舳藭珠_處理兩個通道的數(shù)據(jù),以控制用戶交互上的變化。
三. 基于TCP長連接的通信架構(gòu)
上面的通信架構(gòu)用于業(yè)務(wù)數(shù)據(jù)流的傳輸,流程如下:
1、客戶端使用websocket與服務(wù)端進行通訊,用戶進入答題直播間時建立連接,退出直播間時斷開連接。
2、Nginx對websocket做負載均衡。
3、TCP網(wǎng)關(guān)基于netty實現(xiàn),用于維持長連接和轉(zhuǎn)發(fā)業(yè)務(wù)請求,不負責具體的業(yè)務(wù)邏輯,它和下層業(yè)務(wù)系統(tǒng)(答題系統(tǒng))通過RPC接口進行交互,主要考慮后續(xù)其他業(yè)務(wù)可以復(fù)用TCP網(wǎng)關(guān)層,所以將業(yè)務(wù)下沉??蛻舳撕途W(wǎng)關(guān)之間通過心跳機制保證連接的有效性以及檢測僵尸連接。
4、消息推送(比如彈幕、下發(fā)題目、公布答案等諸多場景)由下層業(yè)務(wù)(答題系統(tǒng))通過MQ通知TCP網(wǎng)關(guān),再由TCP網(wǎng)關(guān)推送給客戶端。
四. 長連接通信中的數(shù)據(jù)傳輸格式定義
通信架構(gòu)中另外比較重要的是數(shù)據(jù)傳輸格式的定義,客戶端和TCP網(wǎng)關(guān)之間,TCP網(wǎng)關(guān)和答題系統(tǒng)之間均采用的是protobuf格式。下面分開說一下比較關(guān)鍵的幾個格式定義。
4.1 客戶端請求消息的格式
1、消息類型標識:-1表示心跳消息、0表示用戶驗證消息、>0 表示業(yè)務(wù)類消息
2、用戶ID:用戶的唯一標識,在前置的登錄流程中已經(jīng)獲得
3、Token:用戶登錄APP后的授權(quán)令牌,在前置的登錄流程中已經(jīng)獲得
4、BizData:真正的業(yè)務(wù)數(shù)據(jù),protobuf序列化后的byte數(shù)組,由下層業(yè)務(wù)自行定義更具體的格式
4.2 客戶端響應(yīng)消息的格式
1、消息類型標識:和請求中的消息類型保持一致
2、狀態(tài)碼:0表示處理失敗,1表示處理成功
3、BizData:真正的業(yè)務(wù)數(shù)據(jù),如果狀態(tài)碼為0,該字段為4字節(jié)的異常碼(100表示token驗證失敗,101表示請求業(yè)務(wù)層失?。?,如果狀態(tài)碼為1,該字段為業(yè)務(wù)層返回的protobuf序列化后的byte數(shù)組,同樣由下層業(yè)務(wù)自行定義更具體的格式
4.3 業(yè)務(wù)數(shù)據(jù)的ProtoBuf格式定義
- 1message Message
- 2{
- 3 MessageType messageType = 1; // 消息類型,枚舉值
- 4 string sequence = 2; // 消息序號
- 6 Request request = 3; // 請求類消息
- 7 Response response = 4; // 響應(yīng)類消息
- 8 Notification notification = 5; // 推送類消息
- 9}
這里的格式設(shè)計比較巧妙,通過Message頂層消息把Request、Response、Notification這3類消息包裝起來,并且定義一個MessageType枚舉值,用來表示消息類型,另外sequence字段表示消息的唯一序列號,需要保證發(fā)送端內(nèi)唯一,這樣發(fā)送端收到Response后可以進行匹配處理。有了上面的統(tǒng)一消息格式,答題系統(tǒng)就可以針對不同的MessageType定義不同的消息處理器,配置好映射關(guān)系后,即可實現(xiàn)消息路由。
五. 系統(tǒng)總體架構(gòu)
1、網(wǎng)關(guān)層:架構(gòu)上同時采用了TCP網(wǎng)關(guān)和HTTP網(wǎng)關(guān),TCP網(wǎng)關(guān)上一章節(jié)已經(jīng)講解,它主要用于維持百萬用戶同時在線,以及答題期間的實時數(shù)據(jù)交互(包括加入直播間、推送題目、答題、推送答案、搶紅包、彈幕推送等)。HTTP網(wǎng)關(guān)為APP端提供Restful接口,用于低頻的數(shù)據(jù)請求,比如活動首頁、排行榜、個人獎金明細、新人邀請、分享等場景。
2、答題系統(tǒng):Dubbo實現(xiàn),最核心的業(yè)務(wù)服務(wù),同時面向C端和B端系統(tǒng)提供RPC接口,包括活動管理、題庫管理、直播間管理、以及面向C端的高并發(fā)接口(比如加入直播間、答題、搶紅包等)。這個集群用到了很多高并發(fā)設(shè)計的通用方法:比如服務(wù)的橫向擴容能力、多級緩存、異步化、限流等,后面的章節(jié)再做具體介紹。另外,通過MQ的事務(wù)消息+對賬機制保證資金流在答題系統(tǒng)和余額系統(tǒng)的一致性。
3、答題運營系統(tǒng):后臺系統(tǒng),供運營人員和直播時的場控人員使用,可以管理活動和題目,以及直播過程中的各種業(yè)務(wù)操作(比如配合主持人的口播下發(fā)題目、公布答案、發(fā)紅包等)。
六. 部署架構(gòu)
直播答題的在線用戶量以及并發(fā)量遠超過商城的交易系統(tǒng),為了減少對主交易流程的影響,采用了上述『私有云+公有云』的混合部署方案,自建機房和云機房之間通過網(wǎng)絡(luò)專線打通。直播答題有關(guān)的應(yīng)用服務(wù)器、存儲服務(wù)器、網(wǎng)絡(luò)帶寬都在云端,可以根據(jù)流量監(jiān)控做到快速擴容,隨著運營計劃的調(diào)整,也可以隨時增減服務(wù)器,靈活性高。
七. 答題系統(tǒng)的高并發(fā)設(shè)計方案
7.1 答題接口的高并發(fā)設(shè)計方案
答題接口的并發(fā)預(yù)計20W QPS,在說設(shè)計方案之前,先簡單列一下答題接口的判斷邏輯:
1、需要判斷答題活動是否仍在進行中
2、需要判斷用戶是否已經(jīng)答錯出局
3、需要判斷用戶輸入的題目是否是當前正在作答的題目
4、需要判斷用戶上一道答對的題和當前這題是否連續(xù)
5、需要判斷用戶作答是否已經(jīng)超時
6、需要判斷用戶的答案是否是正確答案
7、如果答錯了,需要判斷用戶是否有復(fù)活卡
8、如果有復(fù)活卡,需要判斷前面的題是否用過復(fù)活卡了
除了上述判斷邏輯外,還有一些寫操作,比如更新每個答案選項的選擇人數(shù),更新用戶的答對題號或者出局題號,更新復(fù)活卡的使用記錄等,總的來說,答題是一個讀多寫少的接口。為了應(yīng)對高并發(fā),我們采取了以下技術(shù)方案:
1、答題接口的所有邏輯只操作緩存,不操作數(shù)據(jù)庫。采用Write Behind Caching的更新模式(即只更新緩存,在答題結(jié)束后再異步批量更新數(shù)據(jù)庫)。
2、多級緩存:本地緩存+Redis緩存。同時在答題活動開始之前,會先將活動的配置信息,題目,答案等所有靜態(tài)數(shù)據(jù)都預(yù)熱到本地緩存中。
3、Redis 一主多從 + 哨兵的部署架構(gòu),確保高并發(fā)和高可用,同時分業(yè)務(wù)模塊配置了多套Redis實例(用戶、彈幕、直播作答、獎金榜單)做進一步分流。
4、調(diào)整判斷邏輯的順序,上面提到的8個判斷邏輯,其中前4個都屬于安全校驗,因為客戶端已經(jīng)通過交互做了攔截,如果用戶不采取作弊手段肯定都能校驗通過。所以我們將第5、6、7步邏輯做了前置,通過后再進行前4步校驗,這樣大大減少了計算量。
7.2 答題結(jié)果推送的設(shè)計方案
如何在主持人口播公布答案的瞬間,將答題結(jié)果推送給幾十萬作答用戶?因為用戶的作答結(jié)果有非常多的狀態(tài):有答對的和答錯的,有使用復(fù)活卡和未使用復(fù)活卡的,有出局的,不同狀態(tài)下APP端的交互均不同,完全是一種依賴服務(wù)端的有狀態(tài)推送。
為了解決這個并發(fā)計算問題,我們采用了一個比較巧的設(shè)計方案,很好地將有狀態(tài)推送轉(zhuǎn)變成了無狀態(tài)推送:
1、將答題結(jié)果的計算前置到用戶提交答案的時候同步完成(上一節(jié)的方案),這樣相當于將瞬時的計算壓力分散到10秒作答時間里了。
2、用戶的作答結(jié)果也在第1步計算完成后立刻推送給用戶了,不用等到主持人口播公布答案的瞬間,否則的話仍然涉及到并發(fā)讀取作答結(jié)果以及有狀態(tài)推送,對存儲服務(wù)器以及帶寬的瞬時壓力仍然存在。
3、但是作答結(jié)果如果提前推送給客戶端必然存在安全問題,黑客抓包就能提前知道是否答對了,可以利用批量賬號進行作弊。為了解決這個問題,我們對作答結(jié)果采用XOR進行了對稱加密,同時將秘鑰延遲到公布答案的瞬間才下發(fā),而且每道題的秘鑰均是隨機生成的。這樣就很好地解決了安全問題。
4、公布答案的瞬間,我們只需要推送一個非常小的數(shù)據(jù)包給客戶端即可,而且這個數(shù)據(jù)包所有用戶都是一樣的。
7.3 搶紅包接口的高并發(fā)設(shè)計方案
屏幕下紅包雨,用戶觸屏點中紅包就直接拆了,所以搶紅包接口的并發(fā)非常高,1秒內(nèi)單個用戶可觸屏發(fā)起4-5次搶紅包請求,按照百萬用戶在線,并發(fā)最大可達到上百萬QPS,下面說下技術(shù)方案:
1、紅包金額提前計算好并加載到redis中:在創(chuàng)建活動時,運營可配置紅包總金額以及紅包總個數(shù),系統(tǒng)在創(chuàng)建活動時就會提前計算出各個紅包的金額并存儲到redis中,相當于計算前置。
2、客戶端限流:在接口設(shè)計時,我們就預(yù)埋了一個限流因子參數(shù),可由服務(wù)端動態(tài)控制客戶端的限流比例,在通知客戶端搶紅包的接口中,我們根據(jù)當前的在線人數(shù)以及紅包總個數(shù)動態(tài)算出限流因子,控制最多只有10W QPS的請求能發(fā)到服務(wù)端。
3、服務(wù)端限流:根據(jù)服務(wù)器數(shù)量以及紅包總數(shù)量提前計算出每秒令牌的生成數(shù)量,基于guava的RateLimiter進行二次限流。
4、前面3步基本把并發(fā)降下來了,再通過lua腳本保證原子性即可,搶紅包的結(jié)果也是在活動結(jié)束后再異步刷新到數(shù)據(jù)庫。
7.4 其他高并發(fā)的優(yōu)化點
1、Redis緩存的對象要盡可能簡化(用不到的字段不要存),key的長度要盡可能短(高并發(fā)下的瓶頸在于IO),善于利用pipeline組裝多個命令(但是命令個數(shù)不能過多)
2、各種連接池和JVM參數(shù)的調(diào)整:涉及redis連接池、dubbo的線程池、JVM內(nèi)存大小,可以在壓測環(huán)境下找到合理值。
3、答題系統(tǒng)可水平擴展(scale out),同時通過dubbo的分組配置將ToB和ToC接口進行隔離部署,避免相互影響。
最后,關(guān)于直播架構(gòu)再簡單總結(jié)下:
1、音視頻編碼和傳輸,這些基礎(chǔ)性的直播功能,除非公司有錢有實力,否則建議直接用騰訊云或者阿里云的解決方案(斗魚、蘑菇街這些知名的直播應(yīng)用都還用的騰訊云)。
2、架構(gòu)設(shè)計重點放在應(yīng)用本身,根據(jù)直播應(yīng)用的用戶量級和業(yè)務(wù)特性先確定通信架構(gòu)(長連接還是短鏈接,或者兩者混用)。
3、要根據(jù)業(yè)務(wù)高峰來做方案設(shè)計,如果是高并發(fā)場景,要把高并發(fā)當做一個系統(tǒng)性問題去對待:從客戶端到服務(wù)端,從網(wǎng)絡(luò)帶寬到部署架構(gòu),甚至產(chǎn)品設(shè)計等各個維度全盤考慮,要摳各種細節(jié)。