一套簡(jiǎn)潔的即時(shí)通信(IM)系統(tǒng)

原文:https://weibo.com/p/1001603950681689090105

?無(wú)論是IM消息通信系統(tǒng)還是客戶消息系統(tǒng)却盘,其本質(zhì)都是一套消息發(fā)送與投遞系統(tǒng)与帆,或者說(shuō)是一套網(wǎng)絡(luò)通信系統(tǒng)蒸走,其本質(zhì)兩個(gè)詞:存儲(chǔ)與轉(zhuǎn)發(fā)。由于看到最近一個(gè)月內(nèi)業(yè)界有些公司的相關(guān)人員介紹了自己的IM系統(tǒng)整陌,如

  • 攜程高級(jí)經(jīng)理顧慶分享的攜程異步消息系統(tǒng)初期架構(gòu)


    圖一
圖二
  上兩圖顯示了攜程家的消息系統(tǒng)的初期架構(gòu)锁荔,圖一中的架構(gòu)充分體現(xiàn)我朝IT開發(fā)人員"快糙猛"的開發(fā)風(fēng)格,直接用mongodb作為消息隊(duì)列黎做,然后就把系統(tǒng)開發(fā)出來(lái)了叉跛,至圖片2中才稍微見到一個(gè)常見IT系統(tǒng)的接口層。
  • 京東咚咚初期架構(gòu)


    京東咚咚初期架構(gòu)圖

??上圖揭示了京東家的消息系統(tǒng)的初期架構(gòu)蒸殿,作者云下山巔揭示了其特點(diǎn)是“為了業(yè)務(wù)的快速上線筷厘,1.0 版本的技術(shù)架構(gòu)實(shí)現(xiàn)是非常直接且簡(jiǎn)單粗暴的”鸣峭,而且后臺(tái)系統(tǒng)使用.net基于Redis就把一個(gè)IM系統(tǒng)開發(fā)出來(lái)了。
??兩家系統(tǒng)的初期架構(gòu)說(shuō)明酥艳,一套消息系統(tǒng)對(duì)提升自家的服務(wù)質(zhì)量是多么的重要摊溶,可以認(rèn)為現(xiàn)代的服務(wù)型的互聯(lián)網(wǎng)公司成長(zhǎng)過(guò)程就是一套IM系統(tǒng)的進(jìn)化史。
??也說(shuō)明充石,一家的稍微初具實(shí)力的IT公司都可以自己很easy地搭建一套簡(jiǎn)單易用的即時(shí)通信系統(tǒng)莫换。
??本文結(jié)合鄙人對(duì)IM系統(tǒng)的了解,也給出一套初具IM系統(tǒng)系統(tǒng)特點(diǎn)的消息系統(tǒng)模型

1 在線消息系統(tǒng)

??本文只考慮IM系統(tǒng)的在線消息模型骤铃,不考慮其離線消息系統(tǒng)(能夠存儲(chǔ)IM消息的系統(tǒng))拉岁。根據(jù)個(gè)人理解其應(yīng)有的feature如下:

  • A 整個(gè)系統(tǒng)中Server端提供存儲(chǔ)轉(zhuǎn)發(fā)能力,無(wú)論整體架構(gòu)是B/S還是C/S惰爬;
  • B 消息發(fā)送者能夠成功發(fā)送消息給后端喊暖,且得到后端地確認(rèn);
  • C 接收端能否不重不漏地接收Server端轉(zhuǎn)發(fā)來(lái)的沒(méi)有超過(guò)消息生命周期和系統(tǒng)承載能力的消息撕瞧;
  • D 整個(gè)系統(tǒng)只考慮文本短消息[即限制其長(zhǎng)度]陵叽;
  • E 每條消息都有生命周期,如一天丛版,且有長(zhǎng)度限制如1440B【盡量不要超過(guò)一個(gè)物理frame】巩掺,只考慮在線消息的處理,無(wú)論是超時(shí)的消息還是超出系統(tǒng)承載能力的消息[如鍵盤狂人或者鍵盤狂機(jī)器人發(fā)出的消息]都被認(rèn)為是"垃圾消息";
  • F 為簡(jiǎn)單起見硼婿,不給消息很多類型锌半,如個(gè)人對(duì)個(gè)人消息禽车,群消息寇漫,討論組消息等,都認(rèn)為是一種群[下文用channel替代之殉摔,也有人用Room這個(gè)詞]消息類型州胳;
  • G 為簡(jiǎn)單起見,這個(gè)群的建立與銷毀流程本文不述及逸月,也即消息流程開始的時(shí)候各個(gè)消息群都已經(jīng)組建完畢栓撞,且流程中沒(méi)有成員的增減;
  • H 賬戶申請(qǐng)碗硬、用戶鑒權(quán)和天朝獨(dú)有的黃反詞檢查等IM安全層等暫不考慮瓤湘;

根據(jù)以上系統(tǒng)特點(diǎn),先給出一套稍微完備的IM系統(tǒng)的框架圖:


IM系統(tǒng)框架圖

??針對(duì)上圖恩尾,我先給出各個(gè)模塊的中文說(shuō)明弛说,然后分章節(jié)介紹這套系統(tǒng)的各個(gè)模塊的職能,以及相關(guān)的系統(tǒng)流程翰意。

  • 1.系統(tǒng)名詞解釋
1 PC: 單機(jī)型客戶端木人,如windows端和mac端等等信柿;
2 Web/h5: 網(wǎng)頁(yè)客戶端;
3 Android: 手機(jī)移動(dòng)端醒第,取其典型Android端渔嚷,當(dāng)然也有ios端[但是考慮到各家開發(fā)App都是安卓客戶端最先上系統(tǒng)新版本,故用Android代表之]稠曼;
4 broker:文本消息的有線或者無(wú)線接口端形病,考慮到攜程采用了這個(gè)詞,我也姑且先用之霞幅,它提供了消息的接收與投遞功能窒朋;
5 Relay:圖片/語(yǔ)音/視頻 轉(zhuǎn)發(fā)接口端,其后端可以是自家的服務(wù)也可以是第三方服務(wù)(如提供圖片存儲(chǔ)服務(wù)的七牛蝗岖、提供云視頻解決方案的騰訊云等)侥猩;
6 msg chat server:消息邏輯處理端;
7 Router: 在線狀態(tài)服務(wù)端抵赢,存儲(chǔ)在線的用戶以及其登錄的broker接口機(jī)欺劳;
8 Counter: 消息計(jì)數(shù)器,為每個(gè)text等類型的消息分配MSG id铅鲤;
9 Msg Queue: 未讀消息的msg id隊(duì)列划提,存儲(chǔ)每個(gè)client未接收的且未超時(shí)的且未超出隊(duì)列大小的msg id集合;
10 Mysql/mongodb: 消息存儲(chǔ)服務(wù)邢享、用戶資料數(shù)據(jù)鹏往、以及channel成員列表服務(wù)數(shù)據(jù)庫(kù),因?yàn)槎弑容^典型骇塘,所以取用了這個(gè)名字伊履,當(dāng)然你可以在其上部署一層cache服務(wù);
11 Client:客戶端層款违;
12 Interface/If(下文簡(jiǎn)稱If):服務(wù)接口層唐瀑;
13 Logic:消息邏輯處理層,[這層其實(shí)應(yīng)該有系統(tǒng)最多的模塊]插爹;
14 DB:存儲(chǔ)層哄辣,存儲(chǔ)了在線狀態(tài)、消息id以及msg id隊(duì)列和消息內(nèi)容等赠尾;
15 http: 消息發(fā)送和接收協(xié)議力穗,IM協(xié)議中一般理解為long polling消息處理方式,在web端多采用這種協(xié)議气嫁;
16 Websocket: 另一種消息發(fā)送和接收協(xié)議当窗,在移動(dòng)環(huán)境或者采用html5開發(fā)的系統(tǒng)多采用這種協(xié)議;
17 TCP: 另一種消息發(fā)送和接收協(xié)議杉编,在環(huán)境或者采用html5開發(fā)的系統(tǒng)多采用這種協(xié)議超全;
18 UDP: 另一種消息發(fā)送和接收協(xié)議咆霜,某個(gè)不保證提供穩(wěn)定消息傳輸服務(wù)的廠家采用的協(xié)議,也許也是用戶最多使用的協(xié)議嘶朱,它的優(yōu)點(diǎn)是無(wú)論是無(wú)線還是有限環(huán)境下都非扯昱鳎快,又由于http/Websocket的基礎(chǔ)都是tcp協(xié)議疏遏,UDP協(xié)議在環(huán)境擁塞情況下由于不提供擁塞控制等退讓算法脉课,反而會(huì)去爭(zhēng)用網(wǎng)絡(luò)通道,所以在網(wǎng)絡(luò)復(fù)雜的特別是發(fā)生網(wǎng)絡(luò)風(fēng)暴的情況下它會(huì)顯得更快^ _ ^ & ^ _ ^【呵呵噠】财异;
19 RPC: 一種遠(yuǎn)程過(guò)程調(diào)用協(xié)議倘零,提供分布式環(huán)境下的函數(shù)調(diào)用能力;
20 Restful: 一種遠(yuǎn)程服務(wù)提供的架構(gòu)風(fēng)格戳寸,跟RPC比起來(lái)貌似更高級(jí)點(diǎn)呈驶;
    1. 消息發(fā)送流程
      在介紹發(fā)送流程之前,先介紹幾個(gè)基本概念
    • 2.1 pub/sub疫鹊、UIN和session
      ?? 一個(gè)消息系統(tǒng)袖瞻,從宏觀上來(lái)說(shuō),就是一個(gè)PUB/SUB系統(tǒng)拆吆,有消息生成者publisher (or producer)聋迎,有消息中轉(zhuǎn)者broker,有消息處理者msg server枣耀,以及消息消息者subscriber ( or consumer)霉晕。消息消費(fèi)者可以是一個(gè)人,也可以是一群人捞奕,在pub/sub系統(tǒng)之中producer&consumer一起構(gòu)成了一個(gè)channel牺堰,或者稱之為room,或者稱之為group缝彬。
      ??無(wú)論是producer還是consumer萌焰,每個(gè)具體單位都要由系統(tǒng)分配給一個(gè)id哺眯,稱之為UIN(名詞來(lái)源于icq)谷浅。
      ??后端的if層的broker機(jī)器可以在全球或者某個(gè)區(qū)域分布多個(gè),UIN依據(jù)dns系統(tǒng)可以得到if層所有的機(jī)器列表奶卓,如果dns層由于機(jī)器壞掉或者是被攻擊時(shí)不能服務(wù)一疯,那么客戶端應(yīng)該根據(jù)記憶[無(wú)論是上次成功登陸的機(jī)器還是被廠家內(nèi)置的機(jī)器列表]知道某些機(jī)器的ip&port地址,然后根據(jù)測(cè)速結(jié)果來(lái)選擇一個(gè)離其最近的broker夺姑。
      ??UIN在于broker之間進(jìn)行一段時(shí)間內(nèi)有效的會(huì)話服務(wù)墩邀,稱之為一個(gè)session。這個(gè)session存活于一個(gè)長(zhǎng)連接里盏浙,也可以橫跨幾個(gè)長(zhǎng)連接或者短連接眉睹,即session自身依賴的網(wǎng)絡(luò)鏈接是不穩(wěn)定的荔茬。session有效期間內(nèi),Server認(rèn)為UIN在線竹海,session有效期內(nèi)客戶端要定時(shí)地給broker發(fā)送心跳包慕蔚。本文認(rèn)為的session可以是不穩(wěn)定的,即session有效期內(nèi)下發(fā)給客戶端的消息可以丟失斋配,但是可以通過(guò)一些其他手段保證消息被投遞給客戶端孔飒。

    • 2.2 發(fā)送流程
      ??消息的制造者[producer]一般是IM系統(tǒng)的最基本單元UIN[即一個(gè)自然人],既然是一個(gè)自然人艰争,就認(rèn)為其發(fā)送能力有限坏瞄,不可能一秒內(nèi)發(fā)出多于一條的消息,即其消息頻率最高為: 1條msg / s甩卓。高于這個(gè)頻率鸠匀,都被認(rèn)為是鍵盤狂人或者狂躁機(jī)器人,客戶端或者服務(wù)端應(yīng)該具有拒絕給這種人提供服務(wù)或者丟棄其由于發(fā)狂而發(fā)出的消息逾柿。
      ??基于上面這個(gè)假設(shè)狮崩,producer發(fā)出的消息請(qǐng)求被稱為msg req,服務(wù)器給客戶端返回的消息響應(yīng)稱為msg ack鹿寻。整個(gè)消息流程為:

* A client以阻塞方式發(fā)出msg req睦柴,req = {producer uin, channel name, msg device id, msg time, msg content};
* B broker收到消息后毡熏,以u(píng)in為hash或者通過(guò)其他hash方式把消息轉(zhuǎn)發(fā)給某個(gè)msg chat server坦敌;
* C msg chat server收到消息后以 {producer uin【發(fā)送者id】 + msg device id【設(shè)備id】+ msg time【消息發(fā)送時(shí)間,精確到秒】}到本地消息緩存中查詢消息是否已經(jīng)存在痢法,如果存在則終止消息流程狱窘,給broker返回"duplicate msg"這個(gè)msg ack,否則繼續(xù)财搁;
* D msg chat server到Counter模塊以channel name為key查詢其最新的msg id蘸炸,把msg id自增一后作為這條消息的id;
* E msg chat server把分配好id的消息插入本地msg cache和msg DB[mysql/mongoDB]中尖奔;
* F msg chat server給broker返回msg ack, ack = {producer uin, channel name, msg device id, msg time, msg id}搭儒;
* G broker把a(bǔ)ck下發(fā)給producer;
* H producer收到ack包后終止消息流程提茁,如果在發(fā)送流程超時(shí)后仍未收到消息則轉(zhuǎn)到步驟1進(jìn)行重試淹禾,并計(jì)算重試次數(shù);
* I 如果重試次數(shù)超過(guò)兩次依然失敗則提示“系統(tǒng)繁忙” or “網(wǎng)絡(luò)環(huán)境不佳茴扁,請(qǐng)主人稍后再嘗試發(fā)送”等铃岔,終止消息發(fā)送流程。

??上面設(shè)計(jì)到了一個(gè)模塊圖中沒(méi)有的概念:msg cache峭火,之所以沒(méi)有繪制出來(lái)毁习,是因?yàn)閙sg cache的大小是可預(yù)估的智嚷,假設(shè)msg chat server的服務(wù)人數(shù)是40 000人,消息發(fā)送頻率是1條/s纺且,消息的生命周期是4 hour纤勒,消息長(zhǎng)度是1kB。隆檀,那么這個(gè)cache大小 = 1k * 4 * 3600 * 40000 = 576 000 000kB摇天,這個(gè)數(shù)字可能有點(diǎn)恐怖,如果是真實(shí)商業(yè)環(huán)境這個(gè)數(shù)字只會(huì)更小恐仑。其本質(zhì)是一個(gè)hashtable泉坐。
??這個(gè)流程牽涉到一個(gè)比較重要的模塊:Counter,這個(gè)模塊其實(shí)都可以用Redis充當(dāng)裳仆,怎么做你自己想^ _ ^腕让。
??上面還有一個(gè)概念未敘述到:發(fā)送箱,它存儲(chǔ)了所有本地發(fā)送出去的消息歧斟,其中沒(méi)有服務(wù)端分配的msg id的消息都被認(rèn)為是發(fā)送失敗的消息纯丸,待用戶主動(dòng)嘗試發(fā)送或者網(wǎng)絡(luò)環(huán)境重新穩(wěn)定后可以有客戶端嘗試重新發(fā)送流程。
??用戶查看本地歷史消息的時(shí)候静袖,就要依據(jù)msg id把消息排序好展現(xiàn)給用戶觉鼻。至于用戶發(fā)送過(guò)程中看到的消息可以認(rèn)為是本地消息的一個(gè)cache,每個(gè)channel最多給他展現(xiàn)100條队橙,這100條消息的排序要依照每條消息的發(fā)出時(shí)間或者是消息的接收時(shí)間[這個(gè)接收到的消息時(shí)間以消息到達(dá)本機(jī)時(shí)的本地時(shí)鐘為依據(jù)]坠陈。當(dāng)用戶要查看超出數(shù)目如100條消息之外的消息,客戶端要引導(dǎo)用戶去走歷史消息查看流程捐康。

+ 2.3 消息狀態(tài)部分流程
https://kb.cnblogs.com/page/541190/
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末仇矾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子解总,更是在濱河造成了極大的恐慌贮匕,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件花枫,死亡現(xiàn)場(chǎng)離奇詭異刻盐,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)乌昔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門隙疚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人磕道,你說(shuō)我怎么就攤上這事⌒斜” “怎么了溺蕉?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵伶丐,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我疯特,道長(zhǎng)哗魂,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任漓雅,我火速辦了婚禮录别,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘邻吞。我一直安慰自己组题,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布抱冷。 她就那樣靜靜地躺著崔列,像睡著了一般。 火紅的嫁衣襯著肌膚如雪旺遮。 梳的紋絲不亂的頭發(fā)上赵讯,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音耿眉,去河邊找鬼边翼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛鸣剪,可吹牛的內(nèi)容都是我干的讯私。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼西傀,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼斤寇!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起拥褂,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤娘锁,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后饺鹃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體莫秆,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年悔详,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了镊屎。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡茄螃,死狀恐怖缝驳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤用狱,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布运怖,位于F島的核電站,受9級(jí)特大地震影響夏伊,放射性物質(zhì)發(fā)生泄漏摇展。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一溺忧、第九天 我趴在偏房一處隱蔽的房頂上張望咏连。 院中可真熱鬧,春花似錦鲁森、人聲如沸祟滴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)踱启。三九已至,卻和暖如春研底,著一層夾襖步出監(jiān)牢的瞬間埠偿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工榜晦, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留冠蒋,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓乾胶,卻偏偏與公主長(zhǎng)得像抖剿,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子识窿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容