若是在沒有太多經驗可借鑑的狀況下,要設計一套完整可用的移動端IM架構,難度是至關大的。緣由在於,IM系統(尤爲是移動端IM系統)是多種技術和領域知識的橫向應用綜合體:網絡編程、通訊安全、高併發編程、移動端開發等,若是要包含實時音視頻聊天的話,則還要加上難度更大的音視頻編解碼技術(內行都知道,把音視頻編解碼及相關技術玩透的,博士學位均可以混出來了),凡此種種,加上移動網絡的特殊性、複雜性,設計和開發難度不言而喻。
本文分享了一套完整的海量在線用戶的移動端IM架構設計,來自於做者的真實項目實踐總結,包含了詳細的算法原理圖、數據結構定義、表結構定義等等。
即時通信網注:本文中的架構設計從實際應用的角度看,其實並不完美,多處設計對於高吞吐高併發的IM應用來講也是存在單點性能瓶頸的(好比:提供消息交換邏輯的msg_logic服務、提供全局用戶狀態查詢的單點Redis等),另外IM協議設計可能也稍顯混亂(但這是仁者見仁智者見者的事了,不能一律而論)。但文章中的大部分算法原理、協議設計等都是值得借鑑的,總之不必照搬,但至少能給你自已的方案設計帶來靈感,我想這也是本文或即時通信網的其它相似文章的真正價值所在。php
《淺談IM系統的架構設計》
《簡述移動端IM開發的那些坑:架構設計、通訊協議和客戶端》
《一套原創分佈式即時通信(IM)系統理論架構方案》
《從零到卓越:京東客服即時通信系統的技術架構演進歷程》
《蘑菇街即時通信/IM服務器開發之架構選擇》
《騰訊QQ1.4億在線用戶的技術挑戰和架構演進之路PPT》
《微信技術總監談架構:微信之道——大道至簡(演講全文)》
《如何解讀《微信技術總監談架構:微信之道——大道至簡》》
《快速裂變:見證微信強大後臺架構從0到1的演進歷程(一)》
《17年的實踐:騰訊海量產品的技術方法論》
>> 更多同類文章 ……html
整體架構包括5個層級,具體內容以下圖:
各層級的說明以下:
redis
典型算法邏輯部分描述IM系統核心組件及其協做關係,結構圖以下:
客戶端從Iplist服務獲取接入層IP地址(也可採用域名的方式解析獲得接入層IP地址),創建與接入層的鏈接(可能爲短鏈接),從而實現客戶端與IM服務器的數據交互;業務線服務器能夠經過服務器端API創建與IM服務器的聯繫,向客戶端推送消息;客戶端上報到業務服務器的消息,IM服務器會經過mq投遞給業務服務器。
如下將對各子業務的工做原理進行逐一介紹。
算法
用戶請求受權時,可能在另外一個設備(同類型設備)開着軟件處於登陸狀態,這種狀況須要系統將那個設備踢下線,以下圖:
數據庫
注:在第6步和第7步之間,啓動計時器(DelayedQueue或哈希環,時間如5秒),計時器時間到後,探測該條消息狀態,若是消息未送達,考慮經過APNS、米推、個推動行推送。
編程
採用擴散寫(而非擴散讀)的方式。
羣聊是多人社交的基本訴求,一個羣友在羣內發了一條消息:緩存
因爲「消息風暴擴散係數」的存在,羣消息的複雜度要遠高於單對單消息。
羣基礎表:用來描述一個羣的基本信息
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)
業務場景舉例:安全
羣聊流程以下圖所示:
羣聊流程詳細說明:服務器
下圖中,將gate和logic合併爲im-server,拉取離線消息流程以下:
微信
ISO採用APNS,Android真後臺保活,同時增長米推、個推。基本思路:push提示信息,App經過拉離線得到真實消息。
TCP的數據協議以下圖所示,包括header和body兩部分:
消息頭總共20個字節,具體信息以下表:
消息體協議採用ProtocolBuffer(谷歌)協議(詳見文章《Protobuf通訊協議詳解:代碼演示、詳細原理介紹等》),版本3.0.0,該協議在序列化效率、壓縮、可擴展方面都具備優點。如下爲主要流程涉及的協議。
認證(auth) :
登出(logout) :
踢人(kickout) :
心跳(keepalive,noop):
心跳包消息體爲空。
單對單聊天(c2c):
羣聊(c2g):
拉離線(pull):
控制類(ctrl)協議:
MySQL數據庫採用utf8mb4編碼格式(emoji字符問題)。
發送消息表:
保存某個用戶發送了哪些消息,用於復現用戶聊天場景(消息漫遊功能須要)。
推送消息表:
保存某個用戶收到了哪些消息。
羣基本信息表:
羣用戶關係表:
用戶狀態及路由信息:
Redis緩存以uid爲key,檢索channel(socketid),last_packet_time等。
Gate層,session以channel(socketed)爲key,檢索uid,及其餘信息。
交互接口:gate->logic,經過將channel轉換爲uid做爲key。
logic->gate,將uid轉換爲channel做爲key。
其餘緩存信息:
你以爲該怎麼存就怎麼存。
採用商用雲存儲。
可考慮採用HBase,HDFS做爲數據歸檔,或者相關雲存儲服務。