一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)(轉)

一、寫在前面

 

1.一、引言


若是在沒有太多經驗可借鑑的狀況下,要設計一套完整可用的移動端IM架構,難度是至關大的。緣由在於,IM系統(尤爲是移動端IM系統)是多種技術和領域知識的橫向應用綜合體:網絡編程、通訊安全、高併發編程、移動端開發等,若是要包含實時音視頻聊天的話,則還要加上難度更大的音視頻編解碼技術(內行都知道,把音視頻編解碼及相關技術玩透的,博士學位均可以混出來了),凡此種種,加上移動網絡的特殊性、複雜性,設計和開發難度不言而喻。

本文分享了一套完整的海量在線用戶的移動端IM架構設計,來自於做者的真實項目實踐總結,包含了詳細的算法原理圖、數據結構定義、表結構定義等等。

即時通信網注:本文中的架構設計從實際應用的角度看,其實並不完美,多處設計對於高吞吐高併發的IM應用來講也是存在單點性能瓶頸的(好比:提供消息交換邏輯的msg_logic服務、提供全局用戶狀態查詢的單點Redis等),另外IM協議設計可能也稍顯混亂(但這是仁者見仁智者見者的事了,不能一律而論)。但文章中的大部分算法原理、協議設計等都是值得借鑑的,總之不必照搬,但至少能給你自已的方案設計帶來靈感,我想這也是本文或即時通信網的其它相似文章的真正價值所在。php

1.二、參考資料


淺談IM系統的架構設計
簡述移動端IM開發的那些坑:架構設計、通訊協議和客戶端
一套原創分佈式即時通信(IM)系統理論架構方案
從零到卓越:京東客服即時通信系統的技術架構演進歷程
蘑菇街即時通信/IM服務器開發之架構選擇
騰訊QQ1.4億在線用戶的技術挑戰和架構演進之路PPT
微信技術總監談架構:微信之道——大道至簡(演講全文)
如何解讀《微信技術總監談架構:微信之道——大道至簡》
快速裂變:見證微信強大後臺架構從0到1的演進歷程(一)
17年的實踐:騰訊海量產品的技術方法論
>> 更多同類文章 ……html

二、服務器端設計

 

2.一、整體架構設計


整體架構包括5個層級,具體內容以下圖:
一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_1.jpg 

各層級的說明以下:
 redis

  • 用戶端:
    移動端重點是移動端,支持IOS/Android系統,包括IM App,嵌入消息功能的瓜子App,將來還可能接入客服系統;
  • 用戶端API:
    針對TCP協議,提供IOS/Android開發SDK。對於H5頁面,提供WebSocket接口;
  • 接入層:
    接入層主要任務是保持海量用戶鏈接(接入)、攻擊防禦、將海量鏈接整流成少許TCP鏈接與邏輯層通信;
  • 邏輯層:
    邏輯層負責IM系統各項功能的核心邏輯實現。包括單聊(c2c)、上報(c2s)、推送(s2c)、羣聊(c2g)、離線消息、登陸受權、組織機構樹等等內容;
  • 存儲層:
    存儲層負責緩存或存儲IM系統相關數據,主要包括用戶狀態及路由(緩存),消息數據(MySQL也可採用NoSql,如MangoDB),文件數據(文件服務器)。

 

2.二、典型算法邏輯


典型算法邏輯部分描述IM系統核心組件及其協做關係,結構圖以下:
一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_2.jpg 

客戶端從Iplist服務獲取接入層IP地址(也可採用域名的方式解析獲得接入層IP地址),創建與接入層的鏈接(可能爲短鏈接),從而實現客戶端與IM服務器的數據交互;業務線服務器能夠經過服務器端API創建與IM服務器的聯繫,向客戶端推送消息;客戶端上報到業務服務器的消息,IM服務器會經過mq投遞給業務服務器。

如下將對各子業務的工做原理進行逐一介紹。
 算法

2.2.1登陸受權(auth)流程原理


一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_3.jpg 
 

  • 一、客戶端經過統一登陸系統實現登陸,獲得token。
  • 二、客戶端用uid和token向msg-gate發起受權驗證請求。
  • 三、msg-gate同步調用msg-logic的驗證接口
  • 四、msg-logic請求sso系統驗證token合法性
  • 五、msg-gate獲得登陸結果後,設置session狀態,並向客戶端返回受權結果。

 

2.2.2登出(logout)流程原理


一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_4.jpg 
 

  • 一、客戶端發起logout請求,msg-gate設置對應Peer爲未登陸狀態。
  • 二、Msg-gate給客戶端一個ack響應。
  • 三、Msg-gate通知msg-logic用戶登出。

 

2.2.3踢人(kickout)流程原理


用戶請求受權時,可能在另外一個設備(同類型設備)開着軟件處於登陸狀態,這種狀況須要系統將那個設備踢下線,以下圖:
一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_5.jpg 
 數據庫

  • 1-5步,參看Auth流程。
  • 六、Logic檢索Redis,查看是否該用戶在其餘地方登陸。
  • 七、若是在其餘地方登陸,發起kickout命令。(若是沒有登陸,整個流程結束)
  • 八、Gate向用戶發起kickout請求,並在短期內(確保客戶端收到kickout數據)關閉socket鏈接。

 

2.2.4上報(c2s)流程原理


一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_6.jpg 
 

  • 一、客戶端向gate發送數據;
  • 二、Gate回一個ack包,向客戶端確認已經收到數據;
  • 三、Gate將數據包傳遞給logic;
  • 四、Logic根據數據投遞目的地,選擇對應的mq隊列進行投遞;
  • 五、業務服務器獲得數據。

 

2.2.5推送(s2c)流程原理


一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_7.jpg 
 

  • 一、業務線調用push數據接口sendMsg
  • 二、Logic向redis檢索目標用戶狀態。若是目標用戶不在線,丟棄數據(將來可根據業務場景定製化邏輯);若是用戶在線,查詢到用戶鏈接的接入層gate
  • 三、Logic向用戶所在的gate發送數據
  • 四、Gate向用戶推送數據。(若是用戶不在線,通知logic用戶不在線)
  • 五、客戶端收到數據後向gate發送ack反饋
  • 六、Gate將ack信息傳遞給logic層,用於其餘可能的邏輯處理(如日誌,確認送達等)


 

2.2.6單對單聊天(c2c)流程原理


一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_8.jpg 
 

  • 一、App1向gate1發送信息(信息最終要發給App2)
  • 二、Gate1將信息投遞給logic
  • 三、Logic收到信息後,將信息進行存儲
  • 四、存儲成功後,logic向gate1發送ack
  • 五、Gate1將ack信息發給App1
  • 六、Logic檢索redis,查找App2狀態。若是App2未登陸,流程結束
  • 七、若是App2登陸到了gate2,logic將消息發往gate2
  • 八、Gate2將消息發給App2(若是發現App2不在線,丟棄消息便可,這種機率極低,後續離線消息可保證消息不丟)
  • 九、App2向gate2發送ack
  • 十、Gate2將ack信息發給logic
  • 十一、Logic將消息狀態設置爲已送達。


注:在第6步和第7步之間,啓動計時器(DelayedQueue或哈希環,時間如5秒),計時器時間到後,探測該條消息狀態,若是消息未送達,考慮經過APNS、米推、個推動行推送。
 編程

2.2.7羣聊(c2g)流程原理


採用擴散寫(而非擴散讀)的方式。

羣聊是多人社交的基本訴求,一個羣友在羣內發了一條消息:緩存

  • 1)在線的羣友能第一時間收到消息;
  • 2)離線的羣友能在登錄後收到消息。


因爲「消息風暴擴散係數」的存在,羣消息的複雜度要遠高於單對單消息。

羣基礎表:用來描述一個羣的基本信息
im_group_msgs(group_id, group_name,create_user, owner, announcement, create_time)

羣成員表:用來描述一個羣裏有多少成員
im_group_users(group_id, user_id)

用戶接收消息表:用來描述一個用戶的全部收到羣消息(與單對單消息表是同一個表)
im_message_recieve(msg_id,msg_from,msg_to, group_id,msg_seq, msg_content, send_time, msg_type, deliverd, cmd_id)

用戶發送消息表:用來描述一個用戶發送了哪些消息
im_message_send (msg_id,msg_from,msg_to, group_id,msg_seq, msg_content, send_time, msg_type, cmd_id)

業務場景舉例:安全

  • 1)一個羣中有x,A,B,C,D共5個成員,成員x發了一個消息;
  • 2)成員A與B在線,指望實時收到消息;
  • 3)成員C與D離線,指望將來拉取到離線消息。


羣聊流程以下圖所示:
一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_9.jpg 

羣聊流程詳細說明:服務器

  • 一、X向gate發送信息(信息最終要發給這個羣,A、B在線)
  • 二、Gate將消息發給logic
  • 三、存儲消息到im_message_send表,按照msg_from水平分庫
  • 四、回ack
  • 五、回ack
  • 六、Logic檢索數據庫(須要使用緩存),得到羣成員列表
  • 七、存儲每一個用戶的消息數據(用戶視圖),按照msg_to水平分庫(併發、批量寫入)。
  • 八、查詢用戶在線狀態及位置
  • 九、Logic向gate投遞消息
  • 十、Gate向用戶投遞消息
  • 十一、App返回收到消息的ack信息
  • 十二、Gate向logic傳遞ack信息
  • 1三、向緩存(Hash)中更新收到ack的時間。而後在經過一個定時任務,每隔必定時間,將數據更新到數據庫(注意只須要寫入時間段內有變化的數據)。

 

2.2.8拉取離線消息流程原理


下圖中,將gate和logic合併爲im-server,拉取離線消息流程以下:
一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_10.jpg 
 微信

  • 一、App端登陸成功後(或業務觸發拉取離線消息),向IM系統發起拉離線消息請求。傳遞3個主要參數,uid代表用戶;msgid代表當前收到的最大消息id(若是沒收到過消息,或拿不到最大消息id則msgid=0)便可;size表示每次拉取條數(這個值也能夠由服務器端控制)。
  • 二、假設msgid==0,什麼都不作。(參看第6步驟)
  • 三、Im-server查詢用戶前10條離線消息
  • 四、將離線消息推給用戶。假設這10條離線消息最大msgid=110。
  • 五、App獲得數據,判斷獲得的數據不爲空(代表可能沒有拉完離線數據,不用<10條作判斷拉完條件,由於服務端須要下下次拉離線的請求來肯定此次數據已送達),繼續發起拉取操做。Msgid=110(取獲得的離線消息中最大的msgid)。
  • 六、Im-server刪除該用戶msgid<110的離線消息(或者標記爲已送達)。
  • 七、查詢msgid>110的錢10條離線數據。
  • 八、返回給App
  • ……
  • N-一、查詢msgid>140的離線數據,0條(沒有離線數據了)。
  • N  、將數據返回App,App判斷拉取到0條數據,結束離線拉取過程。

 

2.三、後臺PUSH(推送)


ISO採用APNS,Android真後臺保活,同時增長米推、個推。基本思路:push提示信息,App經過拉離線得到真實消息。

三、協議設計

 

3.一、IM協議整體定義


TCP的數據協議以下圖所示,包括header和body兩部分:
一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_11.jpg 

消息頭總共20個字節,具體信息以下表:
一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_12.jpg 

3.二、各具體的IM協議體定義


消息體協議採用ProtocolBuffer(谷歌)協議(詳見文章《Protobuf通訊協議詳解:代碼演示、詳細原理介紹等》),版本3.0.0,該協議在序列化效率、壓縮、可擴展方面都具備優點。如下爲主要流程涉及的協議。

認證(auth) :
一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_13.jpg 

登出(logout) :
一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_14.jpg 

踢人(kickout) :
一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_15.jpg 

心跳(keepalive,noop):
心跳包消息體爲空。

單對單聊天(c2c):
一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_16.jpg 
一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_17.jpg 

羣聊(c2g):
一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_18.jpg 
一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_19.jpg 

拉離線(pull):
一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_20.jpg 

控制類(ctrl)協議:
一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_21.jpg 
一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_23-2.jpg 

四、存儲設計

 

4.一、MySQL數據庫


MySQL數據庫採用utf8mb4編碼格式(emoji字符問題)。

4.二、主要表結構


發送消息表:
保存某個用戶發送了哪些消息,用於復現用戶聊天場景(消息漫遊功能須要)。
一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_22.jpg 

推送消息表:
保存某個用戶收到了哪些消息。
一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_23.jpg 

羣基本信息表:
一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_24.jpg 

羣用戶關係表:
一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_25.jpg 

4.三、水平分庫


一套海量在線用戶的移動端IM架構設計實踐分享(含詳細圖文)_26.jpg 

4.四、Redis緩存


用戶狀態及路由信息:
Redis緩存以uid爲key,檢索channel(socketid),last_packet_time等。
Gate層,session以channel(socketed)爲key,檢索uid,及其餘信息。
交互接口:gate->logic,經過將channel轉換爲uid做爲key。
logic->gate,將uid轉換爲channel做爲key。

其餘緩存信息:
你以爲該怎麼存就怎麼存。

4.五、文件及圖片存儲


採用商用雲存儲。

4.六、數據歸檔


可考慮採用HBase,HDFS做爲數據歸檔,或者相關雲存儲服務。

相關文章
相關標籤/搜索