本文內(nèi)容由百度技術(shù)團(tuán)隊(duì)分享,原題“基于公共信箱的全量消息實(shí)現(xiàn)”涣旨,為了幫助理解歪架,有較多修訂、內(nèi)容重組和重新排版开泽。
1牡拇、引言
百度的IM消息中臺(tái)為百度APP以及廠內(nèi)百度系產(chǎn)品提供即時(shí)通訊的能力,提供包括私聊穆律、群聊惠呼、聊天室、直播彈幕等用戶溝通場(chǎng)景峦耘,并幫助業(yè)務(wù)通過(guò)消息推送觸達(dá)用戶剔蹋。
如今,百度APP新增了一種需要以“低用戶打擾”的形式觸達(dá)全量用戶的場(chǎng)景需求辅髓,而現(xiàn)有的IM消息中臺(tái)主要是基于用戶“私有信箱”通知拆分的機(jī)制(通俗了說(shuō)也就是IM里的“擴(kuò)散寫”)泣崩,所以如果不進(jìn)行改造,是很難低成本洛口、高時(shí)效的滿足該場(chǎng)景訴求矫付。
基于上述問(wèn)題,本文介紹了百度現(xiàn)有IM消息中臺(tái)系統(tǒng)的主要組成第焰,并對(duì)比多種實(shí)現(xiàn)方案的優(yōu)劣买优,以“公有信箱”通知讀擴(kuò)散的技術(shù)方案對(duì)現(xiàn)有IM消息中臺(tái)系統(tǒng)進(jìn)行改造,從而達(dá)成了低成本挺举、高時(shí)效地實(shí)現(xiàn)全量用戶通知推送需求杀赢。
2、全量用戶消息推送需求背景
百度APP新增了需要通過(guò)IM實(shí)時(shí)通知觸達(dá)全量用戶的訴求湘纵,比如2022年12月7日解除疫情管控結(jié)束后脂崔,將經(jīng)過(guò)篩選的官方政策解讀、專題匯總梧喷、知識(shí)科普砌左、實(shí)用工具類介紹等信息,通過(guò)官方號(hào)“x度小助手”下發(fā)觸達(dá)到百度APP用戶铺敌,從而來(lái)有效體現(xiàn)人文關(guān)懷绊困,提高用戶粘性。
在以IM消息服務(wù)進(jìn)行全量用戶消息觸達(dá)時(shí)适刀,需要滿足以下訴求:
具體就是:
1)在觸達(dá)范圍上:希望盡量擴(kuò)大用戶觸達(dá)范圍秤朗,包括百度APP月活用戶、以及非月活用戶但是近期新注冊(cè)或登錄的用戶笔喉;
2)在時(shí)效上:一次全量觸達(dá)取视,希望短時(shí)間內(nèi)完成(比如小時(shí)級(jí)硝皂、甚至分鐘級(jí)),搶占時(shí)效性作谭;
3)在用戶打擾方面:消息觸達(dá)不能給用戶帶來(lái)較大的打擾稽物,每次消息下發(fā),只觸達(dá)一次折欠,不能重復(fù)打擾用戶(但是需要保留回訪入口贝或,滿足用戶二次查看的訴求)。
3锐秦、現(xiàn)有IM消息中臺(tái)的技術(shù)痛點(diǎn)
我們現(xiàn)有的IM(即時(shí)通訊)服務(wù)中咪奖,每個(gè)IM用戶對(duì)應(yīng)一個(gè)用戶信箱。
基于現(xiàn)有的IM技術(shù)實(shí)現(xiàn)方案酱床,如果想完成全量用戶的消息觸達(dá)羊赵,需要把消息推送到每個(gè)用戶的信箱(也就是IM中的擴(kuò)散寫)。
這樣的話扇谣,要完成6億以上的消息寫入(假定每條占用存儲(chǔ)4KB昧捷,每秒寫入2W條消息),在消息寫入時(shí)效性以及存儲(chǔ)資源消耗上罐寨,都是很難接受的靡挥。
且現(xiàn)有的基于用戶私有信箱的方案,在同時(shí)支持多條全量用戶通知消息的場(chǎng)景下鸯绿,擴(kuò)展性也較差跋破。
基于上述需求背景和技術(shù)痛點(diǎn),我們本次的改造目的楞慈,就是要找到一種技術(shù)方案幔烛,從而在特定業(yè)務(wù)場(chǎng)景下通過(guò)改造后的消息服務(wù)啃擦,低成本囊蓝、高時(shí)效的給全量用戶推送內(nèi)容一致的消息通知。
4令蛉、現(xiàn)有IM消息中臺(tái)的主要技術(shù)實(shí)現(xiàn)
在討論改造方案前聚霜,我們有必要介紹一下目前IM消息系統(tǒng)的現(xiàn)狀,包括消息系統(tǒng)的組成珠叔、通知拉取模式蝎宇、用戶信箱等。
4.1 消息系統(tǒng)組成
從普通用戶的直觀體驗(yàn)上看祷安,一個(gè)IM系統(tǒng)可以包括如下元素:
1)用戶主體姥芥;
2)用戶賬號(hào);
3)賬號(hào)關(guān)系汇鞭;
4)聊天會(huì)話凉唐;
5)聊天消息庸追。
用自然語(yǔ)言串一下以上元素就是:
1)“用戶主體”具有“用戶賬號(hào)”;
2)“用戶主體”具有頭像台囱、昵稱等用戶屬性淡溯;
3)“用戶主體”通過(guò)“用戶賬號(hào)”登錄IM系統(tǒng),進(jìn)行聊天簿训;
4)“用戶賬號(hào)”之間的關(guān)注咱娶、屏蔽、免打擾等構(gòu)成“用戶關(guān)系”强品;
5)通過(guò)用戶之間的互動(dòng)環(huán)節(jié)可以產(chǎn)生“聊天消息”膘侮;
6)聊天記錄構(gòu)成了一個(gè)“聊天會(huì)話”。
下面這張圖可能更直觀一些:
從集成消息服務(wù)的業(yè)務(wù)方角度看:
1)一個(gè)IM系統(tǒng)可以包括消息客戶端(消息客戶端UI組件择懂、消息SDK)和消息服務(wù)端喻喳;
2)IM消息可以作為一種服務(wù),嵌入到各業(yè)務(wù)系統(tǒng)中困曙,為業(yè)務(wù)系統(tǒng)提供“實(shí)時(shí)交互”能力表伦;
3)業(yè)務(wù)通過(guò)集成IM服務(wù),提升其用戶體驗(yàn)慷丽;
4)業(yè)務(wù)APP集成IM SDK蹦哼,通過(guò)IM SDK與IM Server交互,完成用戶上行通訊能力要糊;
5)業(yè)務(wù)APP Server通過(guò)與IM Server交互纲熏,完成通知下行觸達(dá)用戶。
下圖為一個(gè)集成了IM SDK的業(yè)務(wù)架構(gòu)圖:
從使用場(chǎng)景來(lái)看锄俄,消息包括:
1)“私信消息”(包括用戶上下行消息)局劲;
2)“通知消息”(業(yè)務(wù)方給用戶推送的下行消息);
3)“群聊”奶赠、“聊天室”鱼填;
4)“直播間彈幕”等。
4.2 消息的通知拉取模式
百度的IM消息系統(tǒng)毅戈,采用通知拉绕煌琛(notify-pull)模式來(lái)感知新消息、拉取新消息苇经。
IM SDK登錄時(shí)赘理,與IM 服務(wù)端建立長(zhǎng)連接(LCS, Long Connect Service),用戶有新的消息時(shí)扇单,通過(guò)長(zhǎng)連接下發(fā)notify商模,實(shí)時(shí)通知用戶的IM SDK。
實(shí)時(shí)notify不寫用戶信箱,因?yàn)閚oitfy不是消息(可以理解為提醒在線用戶有新消息的信號(hào))施流,IM SDK根據(jù)這個(gè)信號(hào)凉倚,來(lái)服務(wù)端拉取消息。
業(yè)務(wù)方server或者其他用戶給該用戶發(fā)送消息后嫂沉,經(jīng)過(guò)IM業(yè)務(wù)處理模塊稽寒,把消息寫入接收者信箱,IM Server會(huì)根據(jù)用戶的登錄和路由信息趟章,給消息接收者(私信場(chǎng)景下也包括“消息發(fā)送者”杏糙,用于消息的多端同步)發(fā)送新消息notify,接收到notify的IM設(shè)備蚓土,通過(guò)IM SDK來(lái)IM Server端拉群晔獭(pull)消息。
4.3 用戶信箱介紹
為了暫存尚未拉取到IM SDK本地的離線消息蜀漆,需要對(duì)消息進(jìn)行服務(wù)端存儲(chǔ)谅河,而消息的離線存儲(chǔ)是通過(guò)消息信箱服務(wù)完成的。
目前百度的IM用戶消息信箱主要包括:
1)用戶私有信箱确丢;
2)群公共信箱(非下文提到的用戶公共信箱)绷耍;
3)直播間彈幕mcast等。
用戶信箱通過(guò)“消息所屬應(yīng)用”+“IM標(biāo)識(shí)用戶的唯一ID”來(lái)標(biāo)識(shí)鲜侥。
就一條消息而言:消息參與者有“消息發(fā)送者”和“消息接收者”褂始,消息收發(fā)雙方的信箱都是相互獨(dú)立的(假設(shè)發(fā)送方刪除了自己信箱的某一條消息,不會(huì)影響消息接受者信箱的消息)描函。
對(duì)于有查看歷史消息訴求的一方來(lái)說(shuō):消息需要入該方的信箱崎苗,比如用戶之間的私信(也就是一對(duì)一單聊)消息需要入發(fā)送者和接收者的信箱。
而對(duì)于全量用戶消息通知的場(chǎng)景:消息不需要存儲(chǔ)發(fā)送者信箱舀寓,而只需要存接收者的信箱胆数。而用戶的信箱排序,是基于信箱Timeline(詳見《現(xiàn)代IM系統(tǒng)中聊天消息的同步和存儲(chǔ)方案探討》)互墓。即消息在信箱內(nèi)部基于時(shí)間線存儲(chǔ)必尼,每條消息對(duì)應(yīng)一個(gè)unix 微秒時(shí)間戳(如第一條消息1679757323320865),用戶進(jìn)行信箱拉取時(shí)轰豆,基于時(shí)間范圍正序或者逆序拉取胰伍。
如下為信箱Timeline的示例:
用戶信箱中的每一條消息記錄都包含四個(gè)主要部分:
1)“消息ID”齿诞;
2)“消息用戶標(biāo)識(shí)”酸休;
3)“消息通用屬性”;
4)“消息業(yè)務(wù)屬性”祷杈。
下面詳細(xì)介紹以上四個(gè)部分:
1)消息ID:為unix微秒時(shí)間戳斑司,不需要全局唯一,只需要特定用戶信箱范圍內(nèi)唯一即可;
2)消息用戶標(biāo)識(shí):包括from_uid宿刮、to_uid互站、contacter;
3)消息通用屬性:包括create_time僵缺、expire胡桃、is_read;
4)消息業(yè)務(wù)屬性:包括category磕潮、type翠胰、priority、business_type自脯、APP_id之景、msgkey、content等膏潮。
如下為一條消息記錄示例:
5锻狗、全量用戶消息推送技術(shù)方案選型
5.1 需求分析
目前百度的IM消息推送機(jī)制中,主要支持:
1)單播:消息推送方式焕参,每次給一個(gè)用戶推送一條消息;
2)批量單播:每次給小范圍用戶推送消息轻纪,比如30個(gè);
3)廣播:基于關(guān)注關(guān)系的推送,如給全量粉絲推送叠纷。
上述三種消息推送機(jī)制推送的消息桐磁,均需要存儲(chǔ)服務(wù)端的用戶私有信箱锐想。為了完成百度APP 6億以上全量月活用戶的消息推送巍实,目前有三種可選的方案逞刷,接下來(lái)我們逐一分析省店。
5.2 方案1:全流程從通知入口推送
該種方式下:需要獲取全量的月活用戶列表夕土,經(jīng)過(guò)IM Server推送入口菠镇,給每一個(gè)用戶推送疫情相關(guān)通知几睛。
該通知寫入到用戶信箱時(shí):
1)若用戶在線邓深,在實(shí)時(shí)拉取該通知阶淘;
2)若用戶離線衙吩,再下次登錄IM服務(wù)時(shí),拉取離線通知溪窒。
該種方案下:推送行為會(huì)覆蓋IM的全流程坤塞,推送的通知會(huì)進(jìn)入每個(gè)月活用戶的私有信箱,服務(wù)壓力大澈蚌。其中增量用戶不會(huì)收到通知推送(這里增量用戶指的是不在月活用戶列表的用戶)摹芙。
5.3 方案2:跳過(guò)通知入口直接寫信箱
該種方式跳過(guò)IM消息推送流程中的中間環(huán)節(jié),直接把通知消息寫入用戶信箱宛瞄。
由于跳過(guò)了中間流程直接寫入信箱浮禾,通知寫入速度主要取決于信箱底層存儲(chǔ)的壓力承受情況。
該種方案下,同方案1一樣盈电,無(wú)法給用戶發(fā)送實(shí)時(shí)通知蝴簇,依賴用戶IM SDK的主動(dòng)消息拉取(斷鏈后重新登錄/新消息提醒拉却抑恪)熬词,無(wú)法給增量用戶發(fā)送通知。
該方案由于跳過(guò)中間環(huán)節(jié)直接寫信箱吸重,風(fēng)險(xiǎn)較大荡澎,無(wú)法直接提供給業(yè)務(wù)方使用,不建議如此操作晤锹。
5.4 方案3:公有信箱實(shí)現(xiàn)機(jī)制
該種公有信箱機(jī)制的邏輯是把通知消息寫入“公共信箱”摩幔。在用戶消息拉取時(shí),合并“用戶私信信箱”+“公共信箱”的消息鞭铆。
5.5 三種方案比較
方案1和2都是寫擴(kuò)散方式或衡,基于現(xiàn)有“用戶私有信箱”的機(jī)制,把通知消息寫入每個(gè)接收通知的用戶私有信箱车遂。
方案2與方案1的差別主要是跳過(guò)了消息中間流程封断,可以避免因?yàn)橹虚g環(huán)節(jié)負(fù)載瓶頸導(dǎo)致整體消息寫入速度過(guò)低。
方案3是讀擴(kuò)散方式舶担,消息不用再寫入接收通知的用戶私有信箱坡疼,而只需要在公共信箱存儲(chǔ)一份。在用戶拉取消息時(shí)衣陶,實(shí)時(shí)拉取公共信箱的消息柄瑰。方案③中可以采用內(nèi)存緩存方案,解決對(duì)公共信箱的讀壓力剪况。
本質(zhì)上來(lái)說(shuō):方案3與方案前兩種相比教沾,是用讀成本(CPU)換寫成本(存儲(chǔ))。
6译断、基于公有信箱技術(shù)方案的全量用戶消息推送實(shí)現(xiàn)
6.1 概述
基于上述方案3的思路授翻,我們進(jìn)行基于公有信箱的全量消息設(shè)計(jì)與實(shí)現(xiàn)。
該種方案中包含兩個(gè)主要流程:
1)全量消息的管理孙咪;
2)用戶私有+公有信箱的拉取堪唐。
6.2 全量消息的管理
全量消息管理主要分為:
1)運(yùn)營(yíng)O端操作平臺(tái):復(fù)用運(yùn)營(yíng)消息平臺(tái);
2)全量消息處理服務(wù):復(fù)用IM服務(wù)的連接層翎蹈、邏輯處理層淮菠、信箱代理、信箱處理杨蛋。
運(yùn)營(yíng)O端平臺(tái)為運(yùn)營(yíng)同學(xué)提供可視化界面兜材,可以對(duì)全量消息進(jìn)行編輯、預(yù)發(fā)布逞力、發(fā)布曙寡、修改、停止寇荧、撤回等操作举庶。
具體就是:
1)接入層:對(duì)接運(yùn)營(yíng)O端,進(jìn)行參數(shù)校驗(yàn)揩抡、轉(zhuǎn)發(fā)IM后端邏輯處理模塊户侥;
2)邏輯處理層:進(jìn)行全量消息的創(chuàng)建、修改峦嗤、停止蕊唐、刪除、撤回等邏輯操作烁设;
3)信箱代理層:復(fù)用IM服務(wù)的信箱CRUD操作替梨;信箱存儲(chǔ)層公共信箱的底層存儲(chǔ)。
全量消息管理流程:
6.3 用戶信箱拉取
用戶通過(guò)IM SDK装黑,以長(zhǎng)連接的方式副瀑,在邏輯處理層進(jìn)行消息拉拉取。
在用戶拉取信箱消息時(shí)恋谭,需要對(duì)“用戶個(gè)人信箱”和“公有信箱”進(jìn)行合并糠睡。于是每次用戶信箱拉取,都需要進(jìn)行信箱的合并拉取疚颊。
6.3.1)公共信箱內(nèi)存緩存機(jī)制:
百度APP的IM用戶狈孔,在IM SDK登錄時(shí)需要拉取信箱中的消息。每次消息拉取時(shí)材义,需要檢查公共信箱中是否有消息除抛。
因此,公共信箱需要能抗住日常和峰值流量(拉取峰值為4.7Wqps)母截。為了防止流量擊穿到忽,流量打到底層的持久化公共信箱MYSQL存儲(chǔ),我們?cè)O(shè)計(jì)了基于內(nèi)存的公共信箱緩存機(jī)制清寇。同時(shí)公共信箱內(nèi)容變化時(shí)喘漏,也要實(shí)時(shí)(或者在能容忍的范圍內(nèi)做到準(zhǔn)實(shí)時(shí))變更內(nèi)存緩存信箱中的消息,我們采用Bthread定期輪詢持久化公共信箱华烟,更新內(nèi)存公共信箱翩迈,輪詢間隔可配置(比如設(shè)置1秒)。
6.3.2)分級(jí)發(fā)布機(jī)制:
同時(shí)盔夜,在邏輯層實(shí)現(xiàn)白名單機(jī)制负饲,支持全量消息在“預(yù)發(fā)布”狀態(tài)下堤魁,僅對(duì)白名單用戶可見,從而達(dá)到分級(jí)驗(yàn)證的效果返十。
白名單的用戶列表通過(guò)邏輯處理成的配置加載妥泉,也支持通過(guò)CURL請(qǐng)求動(dòng)態(tài)修改白名單的配置。
7洞坑、基于公有信箱技術(shù)方案的技術(shù)挑戰(zhàn)
公有信箱的技術(shù)方案盲链,需要解決如下問(wèn)題:
8、基于公有信箱技術(shù)方案的優(yōu)缺點(diǎn)總結(jié)
8.1 優(yōu)點(diǎn)
以公共信箱的方式迟杂,實(shí)現(xiàn)全量用戶消息分發(fā)刽沾,具有:“分發(fā)速度快”、“資源成本低”的特點(diǎn)排拷。
8.2 缺點(diǎn)
但公共信箱的方式也存在一定的局限性侧漓。
8.2.1)不適用于個(gè)性化要求高的場(chǎng)景:
由于消息在公共信箱只存儲(chǔ)一份,下發(fā)消息內(nèi)容固定监氢,無(wú)法很大程度下火架,下發(fā)個(gè)性化消息(當(dāng)然也不是一定無(wú)法下發(fā)個(gè)性化的消息,可以通過(guò)在公共信箱存儲(chǔ)消息模板忙菠,根據(jù)拉取消息的用戶ID獲取個(gè)性化信息何鸡,在消息拉取時(shí),臨時(shí)拼裝消息牛欢,這樣就增大了消息拉取時(shí)的代價(jià))骡男。
8.2.2)不適用于實(shí)時(shí)消息提醒場(chǎng)景:
1)從業(yè)務(wù)場(chǎng)景上看:全量消息優(yōu)先級(jí)低,不需要在全量生效的瞬間讓用戶感知傍睹。
2)從實(shí)現(xiàn)上看:全量消息實(shí)時(shí)消息提醒成本高隔盛。因?yàn)閷?shí)時(shí)消息提醒Notify,需要以類似單播的形式實(shí)時(shí)通知用戶拾稳。和單播的區(qū)別是吮炕,Notify不用觸達(dá)離線用戶,也就是不用寫用戶信箱访得,只需實(shí)時(shí)觸達(dá)在線用戶龙亲。
3)從系統(tǒng)壓力看:全量在線用戶均收到實(shí)時(shí)新消息提醒,會(huì)帶來(lái)信箱拉取請(qǐng)求的瞬時(shí)流量(手機(jī)百度IM SDK長(zhǎng)連接峰值在線1550W悍抑,假定新消息提醒在瞬間下發(fā)鳄炉,同時(shí)在線用戶信箱拉取請(qǐng)求,會(huì)把db打掛的)搜骡。
9拂盯、基于公有信箱技術(shù)方案的落地實(shí)施效果
全量消息目前已經(jīng)在百度APP得到應(yīng)用,包括:重大通知的下發(fā)记靡;百度APP功能更新介紹通知谈竿;消息的撤回团驱,后續(xù)還將推廣到其他的矩陣APP的全量通知推送場(chǎng)景。
舉個(gè)具體的例子:22年Q4宣布疫情解封時(shí)空凸,利用全量消息推送嚎花,低成本、高時(shí)效的完成3條“疫情解封專項(xiàng)”全量消息下發(fā)劫恒。
在這個(gè)例子中贩幻,三次全量消息下發(fā)轿腺,到達(dá)數(shù)據(jù)在2億+(該值小于月活的6億+)两嘴,主要因?yàn)閹讉€(gè)原因:
1)本次全量消息有效期僅3天左右,全量消息有效期內(nèi)登錄IM SDK的用戶才有機(jī)會(huì)拉到全量消息族壳;
2)本次下發(fā)使用了新的消息展示模板憔辫,所以限制了拉取全量消息的百度APP版本,只有高版本百度APP可以拉到仿荆;
3)本次全量消息贰您,限制了僅有百度APP登錄用戶拉取。
10拢操、未來(lái)展望
本文介紹了現(xiàn)有IM消息中臺(tái)系統(tǒng)锦亦,并通過(guò)公有信箱技術(shù)方案的改造,達(dá)成了低成本令境、高分發(fā)速度完成全量用戶消息下發(fā)的設(shè)計(jì)杠园、實(shí)現(xiàn)與應(yīng)用。
在全量用戶消息應(yīng)用方面舔庶,除了業(yè)務(wù)上的使用抛蚁,后續(xù)也可以用于廣播消息、批量單播消息的撤回惕橙。比如由于誤操作發(fā)送了廣播消息瞧甩,用戶已經(jīng)把廣播消息拉到了端,并持久化到端弥鹦,這是可以“以全量消息的方式肚逸,下發(fā)刪除指令”,刪除已經(jīng)緩存到端的垃圾消息彬坏。
我們希望吼虎,通過(guò)消息系統(tǒng)持續(xù)不斷優(yōu)化,為更多的業(yè)務(wù)提供低成本苍鲜、高穩(wěn)定性的即時(shí)通訊能力思灰。
11、相關(guān)資料
[1]?現(xiàn)代IM系統(tǒng)中聊天消息的同步和存儲(chǔ)方案探討
[2]?百度APP移動(dòng)端網(wǎng)絡(luò)深度優(yōu)化實(shí)踐分享(一):DNS優(yōu)化篇
[3]?百度APP移動(dòng)端網(wǎng)絡(luò)深度優(yōu)化實(shí)踐分享(二):網(wǎng)絡(luò)連接優(yōu)化篇
[4]?百度APP移動(dòng)端網(wǎng)絡(luò)深度優(yōu)化實(shí)踐分享(三):移動(dòng)端弱網(wǎng)優(yōu)化篇
[5]?百度直播的海量用戶實(shí)時(shí)消息系統(tǒng)架構(gòu)演進(jìn)實(shí)踐
[6]?深入了解百度開源的分布式RPC框架brpc的方方面面
[7]?百度網(wǎng)盤千萬(wàn)節(jié)點(diǎn)的P2P架構(gòu)設(shè)計(jì)(PPT)
[8]?零基礎(chǔ)IM開發(fā)入門(一):什么是IM系統(tǒng)混滔?
[9]?一套海量在線用戶的移動(dòng)端IM架構(gòu)設(shè)計(jì)實(shí)踐分享(含詳細(xì)圖文)
[10]?一套原創(chuàng)分布式即時(shí)通訊(IM)系統(tǒng)理論架構(gòu)方案
[11]?一套億級(jí)用戶的IM架構(gòu)技術(shù)干貨(上篇):整體架構(gòu)洒疚、服務(wù)拆分等
(本文已同步發(fā)布于:http://www.52im.net/thread-4235-1-1.html)