默認
發表評論 2
想開發IM:買成品怕坑?租第3方怕貴?找開源自已擼?盡量別走彎路了... 找站長給點建議
RainbowChat消息路徑分析及多端消息同步改造方案分享
閱讀(1159) | 評論(2 收藏 淘帖
本文為Freeman對rbchat進行多端登錄消息同步及漫游改造回憶筆記。本文所指“多點”僅指app端與web端同時登錄時所構成的2臺設備的“多端”。

原版中幾個重要概念:


* (1)離線消息:
當對方離線或在線投遞失敗后存儲的消息,拉取后刪除。

* (2)消息記錄:
原版注釋中稱之為“消息收集”,供運營者分析用戶行為收集存儲的消息,目前用于web端歷史消息記錄。可以簡單地認為離線消息是消息記錄的子集

* (3)c2c消息(MT03),一對一好友消息:
不包含陌生人臨時消息(MT42\43)。該類消息“先斬后奏”,由sdk層原封不動轉發給用戶B后通過回調報告給應用層。

* (4)c2s\s2c消息:
包括:陌生人臨時消息、群聊消息、系統指令消息。
該類消息有2種:
  • 一種是用戶A發來的消息(陌生人消息、群聊消息),服務端sdk層收到后先上報給應用層,由應用層處理后新生成一條“改造后的消息”發送給用戶B;
  • 另一種是用戶A進行加好友、消息撤回、禁言、設置管理員、創建/邀請/解散/改名群組等操作通過http方式提交服務端,服務端向相關用戶發送的“指令”消息。

現狀:


  • 1. 已完成手機端登錄互踢改造。
  • 2. 單點收發。 接收方在同時登錄app端和web端的情況下,消息投向由發出方使用何種客戶端類型決定。
  • 3. web端已具有一定的消息漫游功能,但結合app端整體上不具備消息漫游功能。

需求:


  • 1. 實現多點登錄消息同步。
  • 2. 實現消息漫游(無需多臺手機同時漫游)。

總體思路:


  • 1. 向用戶B(消息原始接收用戶)投遞消息時由之前的app與web二選一改為2者兼投遞。
  • 2. 同時向用戶A(消息原始發出用戶)的另一端投遞。
  • 3. web端依舊使用“收集消息”功能作為消息記錄實現消息漫游。
  • 4. app端使用“離線消息”實現消息漫游(局限性:同一條離線消息僅允許一臺手機拉取)。





  • 以上方案中,web端實際將C2C消息也走了S2C的流程,而APP服務端起初設計也是這樣,即上圖中的app改造方案1,但最終采用了方案2,即保留了C2C與S2C消息區分。之所以web端與app端采用了不同的路線,是出于以下考慮:
  • 先行改造的web端,考慮到方案2時web端已改造完成,且web端邏輯較app端相對簡單,C2C消息改走S2C流程沒任何影響。
  • 原版消息邏輯已經過大量實踐驗證,盡可能少的對原版消息邏輯改動,更加穩妥一些。且app端涉及復雜的應答包、QoS機制,故app服務端保留了C2C與S2C消息兩種不同的流程。

關于消息體


  • web端C2C消息雖然走了S2C流程,但發送給用戶B的消息體不變,即p.from仍然是用戶A;
  • 同步“我”發出的消息到“我”的另一設備的消息體由原始消息改造:p.from為“0”,p.to為原來的p.from;
  • 多點同步“我”發出的消息的消息類型p.typeu不另外增設,而是與原始消息類型一致。客戶端通過對比MsgBodyRoot.f與本地用戶來區別處理。

去重、丟包處理


  • app端C2C消息本服直發時不論在線與否直接發,以避免因在線狀態時間差造成的誤判增加重復概率。
  • 多點同步“我”發出的消息時實際是S2C消息,無法通過C2C消息實時應答包機制來實現客戶端超時重發,故需捕獲丟包并處理。因其p.from為“0”,故會進入QoS4SendDaemonS2C隊列中,app服務端應用層通過繼承MessageQoSEventListenerS2C作丟包處理。

關于離線消息


  • 離線消息其作用為離線或斷線重連后及時拉取期間可能遺漏的消息。
  • 原版中app或web任一端拉取離線消息后刪除。改造后僅當app端拉取后才刪除(【接口1008-4-8】增加osType參數)。
  • 同步“我”發出的消息作離線處理入庫后因p.from為"0",客戶端無法判斷該消息原始接收者(聊天對象),故missu_offline_msg表中增加字段firsthand_uid來記錄MsgBodyRoot.t。
  • 改造后離線消息兼任了app端的消息漫游職能,縮小了離線消息對web端的作用范圍。僅在app端本服直發失敗、web端向app端橋發失敗2種情況下存離線消息,web端本服直發失敗不會存離線。
  • app端本身具有客戶端本地持久化存儲歷史消息的功能,如果像web端那樣從服務器拉取歷史消息,勢必會增加服務端的資源性能開支,本地存儲也失去意義。故僅增加對“我”發出的消息也進行離線處理,客戶端本地存儲的歷史消息與服務端的離線消息便形成完整的雙方對話記錄,從而作為手機端的“消息漫游”。如此處理雖然存在不可多臺手機同時拉取到完整的歷史消息的局限性,但從實際應用場景來說僅是為實現web端與手機端之間的同步與漫游,手機端之間是互踢的,所以完全滿足業務需求,而且對原版現有功能充分利用,對服務端又沒有新增資源開支,這一設計是最合理的。對比主流IM產品微信來看,微信干脆沒有實現消息漫游,我們改造的這個效果從這一點來說已經比微信功能豐富了。
  • 原版消息投遞邏輯為本服直發與跨服橋發二選一,所以僅需根據其中一種渠道投遞結果決定是否離線處理。改造后2種渠道均投遞,則需避免重復處理。首先發往app端失敗是肯定要存離線的(因為離線消息兼任了app端的消息漫游職能),那么web端直發失敗是否要存離線呢?如果存,恰巧app端也發送失敗的話,那么就會重復處理;如果不存,影響的只是web端在用戶停留在某一聊天界面狀態下因網絡原因可能會有消息不能即時獲取到,而這一不足之處在用戶切換聊天對象之后即會消除,而且沒有多點同時登錄的話不存在該問題,多點登錄的話還有手機端消息同步提醒,所以這個影響是很微弱的,可以忽略。當然,也可以在入庫時作重復判斷來避免重復,不過會增加資源開支,且基于前面所分析的暫無此必要。

關于“消息收集”


  • 原版中S2C消息由發送方處理,C2C消息由投遞方處理。
  • 改造后各類消息統一由發送方處理。

難點


  • 首先是需要理清原版消息路徑邏輯,包括app服務端的sdk、應用層、web后端sdk、應用層4個部分,其中涉及本服直發、跨發橋發、C2C與S2C不同類型區別處理,還夾雜著離線處理、收集消息業務,回調的默認與自定義方法交叉、方法名重用帶來的名稱與實際含義偏差、QoS機制,這些因素使得看起來簡單的邏輯實際上相當錯綜復雜。
  • 設計出app與web后端sdk、應用層處理流程邏輯,與梳理這些地方一樣,構想那些錯綜復雜的環節,特別是離線與收集消息的處理較燒腦。

前后端應用層后續處理


       起初設想這個改造計劃時主要考慮到上述難點,以為只是難但量不大,實際上除了上述難點外后續處理地方也很多。
  • 首先是因為改造的這個項目中之前做了消息撤回、禁言、設置管理員、用戶主動申請加群等功能,而多點消息同步及漫游則需考慮到這些消息指令也要同步到對方的另一設備、“我”的另一設備,那么這些地方的處理都需要修改,另外原版中的創建群、邀請入群、修改群名、退群、解散群等消息通知也需相應修改。
  • 客戶端對實時收到的同步“我”發出的消息的識別及特殊處理。
  • 圖片、自定義表情等文件類消息同步“我”發出的消息到“我”的另一設備的特殊處理。比如圖片消息,改造前“我”發出的圖片消息其圖片從本地讀取,而多點同步后,同步到“我”的另一端則不存在此圖片,相關邏輯就需改造。
  • 離線消息處理可以說是貫穿整個改造過程中比較棘手的一條支線。(1)離線消息處理的時機;(2)離線消息存儲數據的改造;(3)多種消息類型的區別處理;(4)客戶端對離線消息中“我”發出的消息的特殊處理。
  • 多點同步“我”發出的消息中涉及的昵稱問題。陌生人消息同步到“我”的另一設備時需獲取聊天對象的昵稱,該昵稱的獲取有些不便。現采用如下方法:首先從首頁alarm中查找獲取,如不存在則從服務端查詢該用戶信息,查詢結果回調中得到用戶昵稱再顯示。

后記


以上為對此次改造的一些零碎回憶記錄,因所涉改動地方較多難以全面描述。
本次改造中更加感受到RainbowChat優越性:
  • 能拿到包括SDK層的全部源碼,無任何第三方依賴,因此各種想要實現的功能都完全可以自由diy——這一點是感受最突出的。
  • 已經過大量線上運行實踐驗證,成熟可靠。
  • 作者持續維護更新,后續有保障。
  • 結構條理規范,注釋詳細,可讀性可維護性強。

在此感謝RainbowChat作者,為我等IM開發者提供了很大的方便。



即時通訊網 - 即時通訊開發者社區! 來源: - 即時通訊開發者社區!

上一篇:[已回復] 求教RainbowChat APP端能不能打成架包工具的形式集成下一篇:RainbowChat[專業版] 的v5.1版已發布!
推薦方案
評論 2
花了很多心思,感謝分享。

圖是什么工具畫的?看起來很酷炫
簽名: 《微信后臺基于時間序的新一代海量數據存儲架構的設計實踐》:http://www.4239727.live/thread-2970-1-1.html
引用:JackJiang 發表于 2020-01-29 22:21
花了很多心思,感謝分享。

圖是什么工具畫的?看起來很酷炫

XMind
打賞樓主 ×
使用微信打賞! 使用支付寶打賞!

返回頂部
股票配资平台都找股牛网