百度直播消息服務架構實踐

導讀:直播業務的核心功能有兩個,一個是實時音視頻推拉流,另一個是直播間消息流的收發。本文主要介紹百度直播服務內的消息服務系統的設計實踐和演化。

01

背景

直播間內用戶聊天互動,形式上是常見的 IM 消息流;但直播消息流不僅僅是用戶聊天。除用戶聊天外,直播間內常見的用戶送禮物、進場、點贊、去購買、主播推薦商品、申請連麥等互動行爲的實時提醒,也是通過消息流下發的。此外,直播間關閉、直播流切換等特殊場景,也依賴消息流的實時下發。消息流可以認爲是直播間內主播與用戶間實時互動和直播間實時控制的基礎能力。

02

直播消息 1.0——奠定基礎

如何構建直播的消息系統,又有哪些挑戰需要解決,我們來梳理一下。

直播消息場景分析

直播間內聊天消息,經常被類比於羣聊。羣聊是大家比較熟悉的即時通訊場景,直播間內聊天和羣聊,二者有相似性,但也有本質的區別。

對比二者的特點:

1. 同時參與人數不同:羣聊的參與人數上千人就是很大的羣了;但對於高熱度的大型直播場景,例如國慶、閱兵、春晚等,單直播間累計用戶是百萬甚至千萬量級的集合,同時在線人數可達數百萬人。

2. 用戶與羣和直播間的關係不同:用戶進羣退羣,是相對低頻的操作,用戶集合相對固定,用戶進出的變更頻度不會特別高;而用戶進出直播間,是非常頻繁的,高熱度直播的單直播間每秒面臨上萬用戶的進出變更。

3. 持續時間不同:羣聊建立後,聊天持續時間可能比較長,幾天到數月都有;而直播間大部分持續不超過幾個小時。

根據以上分析,提煉出兩個核心問題:

問題一:直播間內用戶的維護

  1. 單直播間每秒上萬用戶的進出變更;實際進入直播間峯值不超過 2 萬 QPS,退出也不超過 2 萬 QPS。

  2. 單直播間同時數百萬用戶在線

  3. 單直播間累計用戶達千萬量級

支持在線百萬、累積千萬兩個集合,每秒 4 萬 QPS 更新,有一定壓力,但有支持高讀寫性能的存儲應該可以解決,例如 redis。

問題二:百萬在線用戶的消息下發

面對百萬在線用戶,上下行都有大量的消息,從直播用戶端視角分析:

1. 實時性:如果消息服務端做簡單消峯處理,峯值消息的堆積,會造成整體消息延時增大,且延時可能產生很大的累積效應,消息與直播視頻流在時間線上產生很大的偏差,影響用戶觀看直播時互動的實時性。

2. 端體驗和性能:端展示各類用戶聊天和系統消息,一般一屏不超過 10-20 條;如果每秒有超過 20 條的消息下發,端上展示的消息基本會持續刷屏;再考慮到有禮物消息的特效等;大量的消息,對端的處理和展示,帶來持續高負荷。所以,對於一個長時間觀看直播的用戶端來說,如果出現持續的大量消息,端的消息消費會有顯著的性能壓力,且過多消息會有累積效應。

由於問題一不難解決,以下主要討論問題二。

直播消息設計目標


綜合考慮直播業務場景,對於消息服務的需求目標如下:

  1. 實時性方面,端和端的消息要達到秒級;

  2. 性能方面,消息服務能支持同一直播間內百萬以上用戶同時在線下發;

  3. 而對於峯值的過多消息,丟棄是合理適當的處理方式;

  4. 基於合理的端用戶體驗,單直播間內每秒消息數假設不超過 N 條。

現在,問題的核心是,如何做到把不超過 N 條的消息,在 S 秒內,下發到直播間內的百萬用戶,假設 N<=20,S<=2。

普通羣聊壓力分析

普通羣聊消息收發分析

圖 1:羣聊數據流及壓力點

首先,具體分析一下普通羣聊的消息收發流程:

  1. 對於羣 group-1,分配一個羣公共消息信箱 group-mbox-1;

  2. 羣 group-1 內的用戶 user-1,由手機端 APP-1 上發出消息 msg-1;

  3. 服務端接收到消息 msg-1,檢查 user-1 是否有權限,如有權限,將 msg-1 存儲到羣信箱 group-mbox-1,生成相應 msgID-1;

  4. 服務端查詢 group-1 對應的用戶列表 groupUserList-1;

  5. 基於 groupUserList-1 拆分出所有獨立羣用戶:user-1、user-2。。。user-n;

  6. 對於每一個用戶 user-i 來說,需要查詢用戶 user-i 的所在設備 device-i-1、device-i-2、device-i-m(因爲一個賬號可能登錄多個設備);

  7. 對於每個設備 device-i-j 來說,長連接通道都會建立一個獨立的長連接 connect-j 以服務於該設備;但由於 connect-j 是由端上 APP-1 連接到長連接服務的,具有動態性,所以,查詢 device-i-j 與 connect-j 的對應關係時,需要依賴一個路由服務 route 來完成查詢;

  8. 在查得 connect-j 後,可以通過 connect-j 下發 msg-1 的通知 groupmsg-notify-1;

  9. 如果用戶 user-i 正在使用 device-i-j 的手機端 APP-1,用戶 user-i 就可以立即從長連接 connect-j 上收到 msg-1 的通知 groupmsg-notify-1;

  10. 在接收到 groupmsg-notify-1 後,手機端 APP-1 中的消息 SDK 根據端本地歷史消息記錄的最後一條消息 latestMsg 對應的消息 ID 即 latestMsgID,來向服務端發起拉消息請求 fetchMsg,拉取 group-1 中從 latestMsgID+1 到最新的所有消息;

  11. 服務端收到拉消息請求 fetchMsg 後,從 group-mbox-1 中取出 latestMsgID+1 到最新的所有消息,返回給端;如果消息過多,可能需要端分頁拉取;

  12. 端 APP-1 拉取到 group-1 中從 latestMsgID+1 到最新的所有消息,可以做展示;在用戶在會話中閱讀後,需要設置所有新消息的已讀狀態或者會話已讀狀態。

普通羣聊主要壓力

如果完全重用普通羣聊消息的下發通知到端拉取的全過程,對於 user-1 發的一條消息 msg-1,如果需要支持一個實時百萬量級的羣消息,大概有以下幾個每秒百萬量級的挑戰:

首先,秒級拆分出用戶列表 groupUserList-1,需要秒級讀出百萬的用戶列表數據,對於存儲和服務是第一個百萬級挑戰。

第二,對於拆分出羣中的所有獨立用戶 user-i,需要秒級查詢出百萬量級的 device-i-j,對於存儲和服務是第二個百萬級挑戰。

第三,對於所有 device-i-j,通過動態路由服務 route,需要秒級查詢出百萬量級的 connect-j,對於存儲和服務是第三個百萬級挑戰。

第四,對於通過長連接 connect-j 下發時,需要支持秒級下發百萬量級的羣消息通知 groupmsg-notify-1 到對應的 connect-j 上,對於長連接服務是個百萬級的挑戰。

第五,對於收到消息通知的所有端 APP-1,需要支持百萬 QPS 端從服務端拉取消息請求 fetchMsg,對於消息信箱服務,這是也是一個百萬量級的挑戰;考慮到實際各端 latestMsgID 可能不同,可能的優化方式會更復雜一些,帶來的性能影響會更大。

第六,如果在絕大多數用戶是在線聊天的場景,設置已讀狀態也會有百萬量級 QPS 對服務端的壓力。

顯然,完全重用羣聊的消息流程,對消息服務和長連接服務帶來的壓力是巨大的。

普通羣聊優化方案

圖 2:羣聊數據流優化後壓力點 

現在,我們來分析以上每個百萬量級的挑戰,是否有優化的空間。

  1. 對於①拆分用戶列表和②查詢用戶對應設備,如果存儲上將二者合併集中起來,也就是優化直播間內用戶列表的存儲,擴展設備信息,可以減少一次 user->device 的百萬 QPS 查詢,可以優化。

  2. 對於④下行通知和⑤端拉取 fetchMsg 的可靠消息拉取模式,考慮到直播消息允許部分折損丟棄,可以只做單向消息下發,而不做拉取,對於大部分連接保持在線的用戶,也是可以接受的。所以可以優化,只保留下行通知(包含消息體),而捨棄端拉取。

  3. 對於⑥消息設置已讀,直播場景下可以考慮簡化捨棄。

如上優化後,減少了②⑤⑥三個百萬量級壓力請求,但還有①拆分用戶列表③動態路由查詢④長連接下發,這三個百萬量級步驟需要處理。

對於①拆分用戶列表,支持百萬量級用戶列表查詢,比較常規的思路是支持基於羣 groupID 的批量查詢,例如一次可以查出 100 個用戶,1 萬 QPS 查詢就可以支持到百萬;基於羣 groupID 把用戶數據的存儲,分散到多個主從實例和分片上,控制好打散粒度不出現熱點,基本能做到,只是存儲資源可能消耗較多。 

對於③動態路由查詢,表面上看,面臨的問題與①類似,但卻有些不同。因爲羣的用戶列表,是基於羣 groupID 做 key,建立一個表或多個打散的表;而 device-i-j 的查詢是完全分散的,也是需要批量查詢能力,但是完全分散的設備信息查詢,不能只針對特定 key 做優化,需要動態路由服務支持整體上達到百萬 QPS 的查詢性能。

對於④長連接服務下發,由於長連接服務不依賴外部的存儲服務,如果整體要支持百萬量級的下發能力,若長連接單實例能支持 1 萬的下發能力,整體上 100 個實例就能支持到百萬量級下發。

基於以上分析,支持百萬量級的消息下發,初見曙光。似乎只要優化好用戶列表、動態路由的存儲 / 查詢和長連接的容量擴容,但所有的前提是需要消耗大量存儲和機器資源。

考慮到直播業務的實際情況,現實不容樂觀:

一方面,平時沒有熱點直播時,可能單場直播併發在線用戶數峯值不超過 1 萬人,甚至不到 1000;在業務初期,整體直播在線用戶峯值可能也不超過 10 萬。這就意味着,爲了支持百萬量級的峯值,資源整體上有幾十倍的冗餘。

另一方面,如果突然來了一場熱度非常高的直播,可能需要支持的不只是 100 萬量級消息下發,可能是 500 萬以上的量級(例如國慶閱兵、春晚等)。這樣的話,每次大型直播得提前預估可能的在線用戶峯值,如果超過當前設計容量,需要對①用戶列表③動態路由查詢④長連接服務,分別擴容和壓測;或者在可接受的情況下,做服務降級或拒絕服務。

而實際上,在線用戶峯值量級很難估計準確,這樣會造成實際資源利用率很低,擴縮容的操作頻繁,運維成本高。是否選擇這個方案,也是很令人糾結。

普通羣聊多羣組方案

也有人提過拆分多個羣組的方案,例如,如果一個羣組最多支持 1 萬用戶,開 100 個羣就可以支持一百萬用戶;再建立一個虛擬羣,將這 100 個羣關聯起來,似乎可行。

但如果仔細分析,會發現以上提到的幾個問題①拆分用戶列表③動態路由查詢④長連接下發,高壓力依然存在,還是不可避免。

除此之外,多羣組還會引入其他問題:

問題一:多羣組消息不同步。如果兩個用戶在一起看直播,而所屬羣不同,看到的消息會完全不同。

問題二:直播場景用戶是動態進出的,也就是說羣組成員非常不穩定,在線用戶峯值波動也比較大。如果是根據在線人數增長,動態新開羣組,可能第一個羣用戶已經很多了,第二個羣剛開始用戶比較少;或者,在峯值期間開了比較多的羣,隨着熱度降低用戶離開,用戶變得分散,一些羣的用戶可能較稀少,聊天互動較少,這時需要縮容合併羣。如何平衡多個羣的用戶,達到好的業務效果,也是比較難做的。

基於以上分析,我們並沒有選擇多羣組方案。

組播 mcast 方案

支持實時高併發百萬量級同時在線用戶的直播消息架構,組播 mcast 方案的提出及演化。

跳出原有框架思考

是否要採用以上基於羣聊的優化方案,還是可以另闢蹊徑?

先暫時拋開羣收發消息流程,對於消息下發來說,如果一定要說一個步驟是必不可少的,那一定是長連接下發這步了。沒有通過長連接下發,消息就無法最終到達用戶;當然有人說輪詢拉取也可以替代長連接下發,來獲取消息,但顯然輪詢拉取的性能壓力和實時性與長連接下發相比差很多,故不在討論範圍。

如果能簡化爲,給長連接服務下發消息時指定一個類似的 groupID,長連接服務能直接拆分到所有羣組用戶相關的長連接 connect-j,就可以省略掉用戶列表拆分和動態路由查詢的百萬量級查詢。

這樣的話,消息下發的壓力將主要由長連接服務來承受,服務端也不需要對多個系統擴容,直播消息的優化可能會大爲簡化。

根據這個思路,相當於在長連接服務中,對連接 connect 也建立羣組的概念。基於連接組的設想,我們設計了一套長連接的組播 mcast 機制。

長連接組播 mcast 基本概念

  1. 每個長連接組播 mcast 有全局唯一的標識 mcastID。

  2. 長連接組播 mcast 支持創建、刪除、修改、查詢等管理操作。

  3. 長連接組播 mcast 是若干長連接在線用戶的連接 connect 的集合。

  4. 一個用戶 user-i 在設備 device-i-j 上,對於特定應用 APP-k 來說,建立唯一的一個長連接 connect-j-k;(此處暫時不區別登錄用戶和非登錄用戶)。

  5. 長連接組播 mcast 與組內長連接 connect-j-k 的關係維護,不需要額外的獨立存儲,是維護在每個長連接服務的實例上。

長連接組播 mcast 的路由概念

組播 mcast-m 的路由 route-m,是一個長連接服務實例的集合 LcsList,記錄了所有加入 mcast-m 的長連接 connect-i 所在長連接服務實例 lcs-j。

長連接組播 mcast 路由的記錄維護

加入組播 mcast:

  1. 客戶端調用消息 sdk 加入 mcast-m。

  2. 消息 sdk 通過長連接,發出上行請求 mcastJoin(mcast-m)。

  3. 業務層收到來自長連接實例 lcs-i 上的連接 connect-i 的 mcastJoin 請求,校驗 mcast-m 的合法性。

  4. 業務層請求路由層建立基於組播 mcast-m 的組播路由 mcastRoute-m,將長連接實例 lcs-i 加入組播路由 mcastRoute-m 中。

  5. 業務層請求長連接服務層,請求 mcastJoin 所在長連接實例 lcs-i,將請求所在連接 connect-i 加入到 mcastConnectList-m 中。

離開組播 mcast,與加入組播 mcast 基本類似,由客戶端調用消息 sdk 離開 mcast-m,發出上行請求 mcastLeave(mcast-m),長連接服務端更新路由和 mcastConnectList-m 信息。

組播 mcast 消息推送

圖 3:組播 mcast 數據流及壓力點

基於組播 mcast 的長連接消息推送過程,是一個 1:M * 1:N 的擴散放大過程,具體過程描述如下:

  1. 一條消息 msg-1 推送,目的地是 ID 爲 mcast-m 組播;

  2. 後端業務模塊根據目的 mcast-m,做一致性 hash 選擇出 mcast 路由分發模塊實例 mcastRouter- i,發送 msg-1 到 mcastRouter-i;

  3. mcast 分發路由模塊實例 mcastRouter-i,根據 mcast-m 的組播路由 mcastRoute-m,查找所對應的接入實例路由記錄列表 mcastLcsList-m,拆分出 mcast-m 所有的長連接接入實例 lcs-1..lcs-M,分別併發發送 msg-1 到長連接實例上;

  4. 一個長連接服務實例 lcs-j,收到消息 msg-1 推送後,根據組播 mcast-m 查找組播連接列表 mcastConnectList-m,查出 mcast-m 內所有的連接 connect-m-1..connect-m-N,併發推送 msg-1 到消息客戶端 sdk-m-1..sdk-m-N;

  5. 消息客戶端 sdk-m-o 收到 msg-1 後,遞交給上層業務(例如直播 sdk)。

組播 mcast 機制的性能評估

現在分析一下以上的組播 mcast 機制的性能壓力:

  1. 組播 mcast 的路由維護,主要壓力在於 mcastJoin 和 mcastLeave,而 Join 的量級峯值請求很難超過 2 萬 qps;訪問壓力比百萬低兩個數量級。

  2. 組播 mcast 的消息推送流程,在一級路由 mcastRoute 拆分到長連接實例時,一般在幾十到百量級,成本很低。

  3. 組播 mcast 在長連接單實例內的消息推送,是單進程內的多連接併發發送,經優化後線上實測,在單實例保持 25W 長連接的情況下,單實例壓測可達 8Wqps 的 mcast 穩定下發,保守按 5Wqps 容量評估;多個長連接實例間,是完全的併發,可以較容易的水平擴容。

  4. 綜上可知,對於 100Wqps 的下發,20 個長連接實例就可以完全負荷 (20*5W=100W),且有一定裕量。如果 500Wqps 的下發,也不超過 100 實例;1000W 的下發,如果以 8W 單實例較大的負荷承載,125 實例就可以支持。

gwaGl3

看上去,基於以上組播 mcast 機制,我們建立了一套高效的支持百萬量級 QPS 的長連接下發機制,當前長連接服務的容量就可以支持,基本不用擴容。但是否能完全滿足直播業務場景需求,還需要進一步討論。

消息峯值問題

對於每秒 1 條消息,擴散到 100W 用戶,甚至 500W 用戶,以上組播 mcast 機制似乎都能應對。

但直播間內消息的實際情況是,熱門的直播每秒用戶上行聊天消息會有很多,除聊天消息外,直播間還有人數、進場、點贊、分享等定期和不定期發送的很多種類系統消息。

如果假設每秒峯值有 100 條各類消息,100W*100=1 億,簡單按單實例 5Wqps 算,需要 2000 個實例才能支持,雖然比老的羣聊系統應該好很多,但系統還是遇到大量資源冗餘或應對峯值需要大量擴容的老問題。是否能有更好的解決方式?

延時聚合

這裏我們考慮常見的一個優化思路,是通過批量聚合的模式來提高系統性能。如果將這 100 條消息,每秒聚合打包一次來統一下發,QPS 還是 100W,長連接系統的下發 QPS 不變,但每秒下發消息量級可以達到 1 億,這個聚合方案實測是可行的。聚合模式,我們付出的成本是消息時延的上升,1 秒的聚合平均時延增加 500ms,用戶體驗損失不算大,但系統下發消息量級可以提升百倍,綜合評估成本收益來看是合理的。考慮到直播的實際場景,大多數場景下秒級的聚合和時延是可以接受的。

消息帶寬問題

聚合延時下發,長連接單實例 QPS 問題解決了,隨之而來的是,長連接單實例下發的帶寬壓力問題。例如,長連接單實例需要下發 10000 長連接時,每秒 100 消息,消息平均 2K 字節,實際帶寬爲 2K10010000*8=15625Mbps,這已經超過單物理機的萬兆網卡的帶寬容量。

另一方面,從全局帶寬來看,也高達 1.5Tbps,帶寬資源對於機房出口也會帶來壓力,這樣的帶寬成本過高,需要削減帶寬使用或有更好的替代方案。

面對下發數據量帶寬消耗過大的問題,在不改動業務數據的前提下,我們採用了數據壓縮的解決方案。而壓縮是 CPU 密集型的操作,由於直播業務的實時性,不能簡單考慮壓縮比,在綜合平衡壓縮比、壓縮時延和壓縮 CPU 消耗後,調優壓縮庫後實測的平均壓縮比達到 6.7 : 1,數據量壓縮到原來的 15% 左右,這樣 15625Mbps*15%=2344Mbps=2.29Gbps;單機萬兆網卡的帶寬容量,最多承載 4.27 萬的長連接下發,雖然沒有達到 5 萬,基本也可以接受。

從全局帶寬來看,峯值也削減到不超過 230Gbps,收益很明顯。

qqgmiv

客戶端性能問題

進一步考慮,直播場景下,不僅是有較高的峯值消息量級,而是在直播過程中有持續的高消息量級壓力;這不僅對於服務端是壓力,對於客戶端來說也是個挑戰。持續的高消息量級,一方面,客戶端在接收、展示等方面有明顯的壓力;另一方面,直播界面上過多過快的消息刷新,對於用戶體驗也是有害無益的。

所以,在綜合平衡用戶體驗和客戶端性能的基礎上,消息服務端增加了結合消息優先級的分級頻控限速機制,單用戶客戶端並不需要承受每秒 100 條的壓力,削減每秒下發消息後,長連接單實例每秒下發 5-8 萬長連接,CPU 和帶寬都是可以穩定支持的。

實時消息問題

我們提供了基於消息優先級的實時下發機制,對於高優消息可以立即觸發聚合下發,不會增加聚合延時;而對於普通中低優消息,還是做延時聚合下發。

用戶在線問題

組播 mcast 機制的出發點,在百萬量級高併發在線的場景下,保障在線用戶的消息到達,允許不在線用戶接收消息的部分折損,付出合理的技術複雜度和成本,取得服務質量和性能平衡。

而針對在線用戶的消息到達,還有個關鍵問題是如何保障用戶的長連接在線。

爲了提升長連接服務的接入穩定性和可達性,我們在以下幾個方面做了優化。

長連接服務在國內三大運營商的華北華東華南區域均部署了接入點入口;針對有部分國外用戶的直播場景,增加了香港機房的獨立接入點入口。

針對部分用戶的 DNS 劫持問題和解析錯誤問題,消息 SDK 接入了 HTTPDNS 服務並優化本地緩存,形成多級域名解析保障體系,提升了域名解析的可靠性,減少了 DNS 劫持和錯誤率。

長連接的心跳是保活探活的重要手段,針對直播場景實時性高的特點,爲了儘快發現長連接斷鏈,在組播 mcastJoin 後,長連接心跳也調整爲間隔更短、服務端動態可控的智能心跳。這樣在及時發現連接異常後,消息 SDK 可以快速主動重新建連。

在直播間用戶已加入組播 mcast 的情況下,如果長連接斷鏈,長連接服務端會主動或被動的觸發清除組播 mcast 成員。而長連接重建連恢復時,直播業務層也需要監聽連接恢復信號,重新加入組播 mcast,以恢復組播 mcast 的消息通路。

組播 mcast 小結

綜上所述,組播 mcast 機制,有效的解決了百萬量級同時在線用戶的消息實時下發問題;對於短時斷鏈和消息過多,允許部分消息的丟棄;滿足了直播場景消息的設計目標。

組播 mcast 機制特點是:

  1. 消息服務和路由層壓力較輕,整體壓力只由長連接層承載,易於水平擴容。

  2. 基於延時聚合下發,輔以壓縮限速,可以很好的解決下行 QPS 與帶寬的性能問題。

  3. 系統整體下行的 QPS 和帶寬是完全可控的。100W 在線用戶的下行最大 QPS 是 100W,500W 在線用戶的下行最大 QPS 是 500W。單實例的下發能力 5-8 萬 QPS 是穩定的。因此,可以很容易判斷整體的系統容量,特殊場景是否需要擴容。

  4. mcast 機制雖然是針對直播場景提出的,但本身設計具有通用性,可以應用於其他需要實時在線大量用戶分組的消息推送場景。

03

直播消息 2.0 —— 持續發展

在組播 mcast 機制解決了百萬量級的在線用戶實時消息下發後,直播消息的場景不斷擴大,不斷有直播創新業務提出新的消息需求。相應的,組播 mcast 的服務機制也需要與時俱進,不斷在深度和廣度上拓展優化。以下重點介紹一下歷史消息和禮物消息。

歷史消息

對於剛進入直播間的用戶來說,需要看到一些最近的聊天記錄,以增強聊天互動氛圍並幫助瞭解直播的進展;對歷史聊天記錄感興趣額用戶,還可以追溯更多的消息歷史。這就產生了聊天曆史的需求。

爲了支持這類歷史消息的需求,解決方案是對於每個組播 mcast 申請開通一個組播公共消息信箱 mcast-mbox 服務。

  1. 對於用戶消息和其他有持久化需要的消息,全部寫入這個消息信箱。

  2. 用戶可以指定組播 mcastID,按時間區間和要拉取得消息條數,來獲取組播 mcast 的歷史消息。

補充說明一下消息信息的概念和應用。

消息信箱服務概念

  1. 消息信箱內的一條消息 msg,有唯一的消息標識符 msgID。

  2. 一條消息 msg,還包括有發送方信息、接收方信息、消息類型、消息內容等字段,此處可以暫時忽略。

  3. 每條消息可以設置過期時間,消息過期後不能訪問到。

  4. 每條消息可以設置已讀狀態。

  5. 一個消息信箱 mbox,有唯一的信箱標識符 mboxID。

  6. 一個消息信箱 mbox 是一個容器,存儲有序的消息列表 msgList;消息列表 msgList 按 msgID 排序的。

  7. 消息信箱服務,對指定信箱 mbox 支持單條消息或批量消息的寫入。

  8. 消息信箱服務,對指定信箱 mbox 支持基於 msgID 的單條消息或批量消息的查找。

  9. 消息信箱服務,對指定信息 mbox 支持從 msgID-begin 到 msgID-end 的範圍查找。

實際上,最常用的就是基於 msgid 範圍的消息拉取;這裏的消息信箱服務是時間線 timeline 模型,有興趣的同學可以進一步參考時間線 timeline 模型的相關信息。

禮物消息

圖 4:禮物消息

禮物消息場景分析:

  1. 用戶送禮給主播,主播側需要儘快、可靠地收到禮物消息通知,才能及時的給予用戶反饋。

  2. 送出禮物的用戶,本地就可及時展示禮物效果,無消息通知強訴求。

  3. 直播間內其他用戶,需要收到禮物消息,以展示禮物效果,提升直播間互動氛圍,激發其他用戶送禮。

  4. 禮物消息涉及用戶訂單和購買行爲,需要由服務端確認發出。

  5. 禮物消息優先級明顯高於其他聊天消息、系統消息。

基於以上分析,直播消息提出以下技術方案:

  1. 增加一個獨立的可靠消息組播 mcast 通道(如圖 4 中組播 mcast-2),專供高優可靠消息的收發;與其他普通消息、系統消息在數據流層面隔離,減少相互干擾;

  2. 對於普通用戶側的端消息 SDK,禮物消息組播 mcast 通道雖然是新增獨立通道,消息收發邏輯與普通消息組播 mcast 通道保持一致;

  3. 對於主播側,端消息 SDK 對於禮物消息組播 mcast 通道,需要支持推拉結合模式,以保障禮物消息的全部到達;即使有短暫的掉線,也需要取到全部禮物消息;

  4. 對於主播側,在極端情況下,如果長連接建連有異常,消息 SDK 可以通過短連接接口輪詢,來拉取禮物組播 mcast 信箱消息來兜底。

基於以上獨立的可靠消息組播 mcast 通道方案,在未剔除一些異常場景的情況下,如主播下線未關播、數據偶發打點丟失等,禮物消息的觸達率已達到 99.9% 以上。

直播消息其他方面的發展

在百度直播的發展歷程中,直播消息服務還面臨着許多其他基礎性問題和創新業務帶來的其他挑戰。現在這些問題都有了較好的解決方案,以下列舉一些,供大家學習參考:

  1. 如何支持多種客戶端場景,安卓、iOS、H5、小程序、PC。

  2. 如何支持同一場直播的消息在百度 APP 和好看、全民、貼吧等矩陣 APP 的打通。

  3. 如何支持非登錄用戶。IM 一般是支持登錄用戶,而直播場景也需要支持非登錄用戶。

  4. 長連接服務如果出了嚴重問題,是否有端獲取消息的降級通道。

  5. 直播消息審覈的機審人審如何做,如何支持先發後審和先審後發。

  6. 如何支持跨多個直播間的消息。

  7. 直播消息服務是如何支持創新業務的,如答題直播、直播帶貨、直播連麥等。

限於篇幅,以上問題在此不再做具體討論,有興趣同學歡迎直接聯繫探討。

04

回顧展望

自百度直播上線以來幾年間,直播消息服務迎難而上,一路披荊斬棘爲百度直播保駕護航,爲百度直播提供了堅實的技術支撐和保障。

未來,在支持直播創新業務、更細粒度的消息分級服務、直播消息基礎服務的穩定性和性能等方面,直播消息服務會繼續努力,夯實基礎,持續創新,以支持直播業務更好更快的發展。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/rPsaws4UpQyeRB-9pSfxGg