融雲技術分享:全面揭祕億級IM消息的可靠投遞機制

本文由融雲技術團隊原創分享,原題「IM 消息同步機制全面解析」,爲使文章更好理解,對內容進行了從新概括和細節修訂。html

一、內容概述

即時通信(IM)系統最基礎、最重要的是消息的及時性與準確性,及時體如今延遲,準確則具體表現爲不丟、不重、不亂序。緩存

綜合考慮業務場景、系統複雜度、網絡流量、終端能耗等,咱們的億級分佈式IM消息系統精心設計了消息收發機制,並不斷打磨優化,造成了如今的消息可靠投遞機制。服務器

總體思路就是:markdown

  • 1)客戶端、服務端共同配合,互相補充;
  • 2)採用多重機制,從不一樣層面保障;
  • 3)拆分上下行,分別處理。

本文根據融雲億級IM消息系統的技術實踐,總結了分佈式IM消息的可靠投遞機制,但願能爲你的IM開發和知識學習起到拋磚引玉的做用。網絡

二、客戶端與服務端消息交互總體原理

2.1 概述

一個完整的IM消息交互邏輯,一般會爲兩段:架構

  • 1)消息上行段:即由消息發送者經過IM實時通道發送給服務端;
  • 2)消息下行段:由服務端按照必定的策略送達給最終的消息接收人。

2.2 消息上行段

消息上行段主要就是依賴IM的實時通道將消息傳遞給服務端。分佈式

這個階段的消息可靠投遞,須要從協議層進行保證,協議層須要提供可靠、有序的雙向字節流傳輸,咱們是經過自研的通訊協議 RMTP(即 RongCloud Message Transfer Protocol)實現的。oop

客戶端與服務端之間使用長鏈接,基於 RMTP 協議傳輸數據。性能

RMTP協議交互示意圖:學習

如上圖所示,協議層經過 QoS、 ACK 等機制,保證IM消息上行段數據傳輸的可靠性。

2.3 消息下行段

通過總結,消息下行段主要有三種行爲。

1)客戶端主動拉取消息,主動拉取有兩個觸發方式:

  • ① 拉取離線消息:與 IM 服務新創建鏈接成功,用於獲取不在線的這段時間未收到的消息;
  • ② 定時拉取消息:在客戶端最後收到消息後啓動定時器,好比 3-5 分鐘執行一次。主要有兩個目的,一個是用於防止因網絡、中間設備等不肯定因素引發的通知送達失敗,服務端客戶端狀態不一致,一個是可經過本次請求,對業務層作狀態機保活。

2)服務端主動-發送消息(直髮消息):

這是在線消息發送機制之一,簡單理解爲服務端將消息內容直接發送給客戶端,適用於消息頻率較低,而且持續交互,好比二人或者羣內的正常交流討論。

3)服務端主動-發送通知(通知拉取):

這是在線消息發送機制之一,簡單理解爲服務端給客戶端發送一個通知,通知包含時間戳等可做爲排序索引的內容,客戶端收到通知後,依據自身數據,對比通知內時間戳,發起拉取消息的流程。

這種場景適用於較多消息傳遞: 好比某人有不少大規模的羣,每一個羣內都有不少成員正在激烈討論。經過通知拉取機制,能夠有效的減小客戶端服務端網絡交互次數,而且對多條消息進行打包,提高有效數據載荷。既能保證時效,又能保證性能。

客戶端服務端下行段消息交互示意圖:

三、客戶端與服務端消息交互具體實現

正如上節所言,咱們將消息的交互流程進行了拆分:即拆分出上下行。

3.1 上行

在上行過程保證發送消息順序,爲了保證消息有序, 最好的方式是按照 userId 區分,而後使用時間戳排序。那麼分佈式部署狀況下,將用戶歸屬到固定的業務服務器上(PS:指的是同一帳號的不一樣端固定鏈接到相同的業務服務器上),會使得上行排序變得更容易。同時歸屬到同一個服務器,在多端維護時也更容易。

客戶端鏈接過程:

  • 1)客戶端經過 APP server ,獲取到鏈接使用的 token;
  • 2)客戶端使用 token 經過導航服務,獲取具體鏈接的 IM 接入服務器(CMP),導航服務經過 userId 計算接入服務器,而後下發,使得某一客戶端能夠鏈接在同一臺接入服務器(CMP)。

示意圖以下:

小結一下就是: 客戶端發出消息後,經過接入服務,按照 userId 投遞到指定消息服務器,生成消息 Id, 依據最後一條消息時間,確認更新當前消息的時間戳(若是存在相同時間戳則後延)。而後將時間戳,以及消息 Id,經過 Ack 返回給客戶端 ; 而後對上行消息使用 userId + 時間戳進行緩存以及持久化存儲,後續業務操做均使用此時間戳。

以上業務流程咱們稱爲上行流程,上行過程存儲的消息爲發件箱消息。

PS: 關於消息ID,須要補充說明一下:

咱們採用全局惟一的消息 ID 生成策略。保證消息可經過 ID 進行識別,排重。消息ID的結構以下圖所示。

如何實現分佈式場景下惟一 ID 生成,具體請閱讀:《IM消息ID技術專題(三):解密融雲IM產品的聊天消息ID生成策略》。

3.2 下行

消息節點在處理完上行流程後,消息按照目標用戶投遞到所在消息節點,進入下行流程。

下行過程,按照目標 userId 以及本消息在上行過程當中生成的時間戳,計算是否須要更新時間戳(正向)。

若是須要更新則對時間戳進行加法操做,直到當前用戶時間戳不重複。

如此處理後,目標用戶的存儲以及客戶端接收到消息後的排重能夠作到一致,而且能夠作到同一個會話內的時間戳是有序的。從而保證同一個接收用戶的消息不會出現亂序。

至此: 咱們已經介紹完了消息的下行交互過程,消息下行過程當中的具體實現方式並不簡單,如下將詳細展開。

1)直髮消息:

即服務端主動發送(給目標客戶端)的消息:

  • 1)客戶端 SDK 依據本地存儲的最新消息時間戳判斷,用來作排序等邏輯;
  • 2)對同一個用戶直髮消息1條,其餘轉通知。通知拉取時候客戶端選擇本地最新一條消息時間戳做爲開始拉取時間;
  • 3)在消息發送過程當中,若是上一條消息發送流程未結束,下一條消息則不用直髮(s_msg),而是用通知(s_ntf)。

直髮邏輯示意圖:

2)通知拉取:

即服務端主動發送通知(給目標客戶端):

  • 1)服務端在通知體中攜帶當前消息時間戳。投遞給客戶端;
  • 2)客戶端收到通知後,比對本地消息時間戳,選擇是否發拉取消息信令;
  • 3)服務端收到拉取消息信令後,以信令攜帶的時間戳爲開始,查詢出消息列表(200 條或者 5M),並給客戶端應答;
  • 4)客戶端收到後,給服務端 ack,服務端維護狀態;
  • 5)客戶端拉取消息時使用的時間戳,是客戶端本地最新一條消息的時間戳。

示意圖:

在上圖中,3-7 步可能須要循環屢次,有如下考慮:

  • a、客戶端一次收到的消息過多,應答體積過於龐大,傳輸過程對網絡質量要求更高, 所以按照數量以及消息體積分批次進行;
  • b、一次拉取到的消息過多,客戶端處理會佔用大量資源,可能會有卡頓等,體驗較差。

3)服務端直髮消息與通知拉取切換邏輯:

主要涉及到的是狀態機的更新。

下面示意圖集成直髮消息與通知拉取過程針對狀態機的更新:

至此,消息收發的整個核心流程介紹完畢,餘下的內容將介紹多端在線的消息同步處理。

四、多端在線的消息同步

多端按照消息的上下行兩個階段,一樣區分爲發送方多端同步以及接收方多端同步。

4.1 發送方多端同步

在前面客戶端鏈接 IM 服務過程當中(見本文 4.1節),咱們已經將同一個用戶的多個客戶端匯聚在了同一臺服務,那麼維護一個 userId 的多端就會變得很簡單。

具體邏輯是:

  • 1)用戶多個終端連接成功後,發送一條消息,這個消息到達 CMP(IM 接入服務) 後,CMP 作基礎檢查,而後獲此用戶的其餘終端鏈接;
  • 2)服務把客戶端上行的消息,封裝爲服務端下行消息,直接投遞給用戶的其餘客戶端。這樣完成了發送方的多端抄送,而後將這條消息投遞到 IM 服務。進入正常發送投遞流程。

針對上面的第2)點,發送方的多端同步沒有通過 IM Server,這麼作的好處是:

  • 1)比較快速;
  • 2)通過越少的服務節點,出問題的概率越小。

4.2 接收方多端同步

具體邏輯是:

  • 1)IM 服務收到消息後,先判斷接收方的投遞範圍,這個範圍指的是接收方用戶的哪些的終端要接收消息;
  • 2)IM 服務將範圍以及當前消息,發送到 CMP,CMP 依據範圍,匹配接收方的終端,而後投遞消息。

接收方多端消息同步範圍的應用場景,通常都是針對全部終端。

但有一些特殊業務: 好比我在 A 客戶端上,控制另外某個端的狀態,可能須要一些命令消息, 這時候須要這個做用範圍,針對性的投遞消息。

到此,咱們分享完了有關 IM 消息核心處理流程,經過層層拆解邏輯,提供了可靠的消息投遞機制。(本文已同步發佈於:www.52im.net/thread-3638…

五、參考資料

[1]《零基礎IM開發入門(二):什麼是IM系統的實時性?
[2]《零基礎IM開發入門(三):什麼是IM系統的可靠性?
[3]《零基礎IM開發入門(四):什麼是IM系統的消息時序一致性?
[4]《IM消息送達保證機制實現(一):保證在線實時消息的可靠投遞
[5]《IM消息送達保證機制實現(二):保證離線消息的可靠投遞
[6]《IM開發乾貨分享:如何優雅的實現大量離線消息的可靠投遞
[7]《理解IM消息「可靠性」和「一致性」問題,以及解決方案探討
[8]《如何保證IM實時消息的「時序性」與「一致性」?
[9]《IM羣聊消息如此複雜,如何保證不丟不重?
[10]《從客戶端的角度來談談移動端IM的消息可靠性和送達機制
[11]《一套億級用戶的IM架構技術乾貨(下篇):可靠性、有序性、弱網優化等

如下是融雲技術團隊分享的其它文章:

[1]《IM消息ID技術專題(三):解密融雲IM產品的聊天消息ID生成策略
[2]《融雲技術分享:基於WebRTC的實時音視頻首幀顯示時間優化實踐
[3]《融雲技術分享:融雲安卓端IM產品的網絡鏈路保活技術實踐

相關文章
相關標籤/搜索