请选择 进入手机版 | 继续访问电脑版

默认
发表评论 2
想开发IM:买成品怕坑?租第3方怕贵?找开源自已撸?尽量别走弯路了... 找站长给点建议
RainbowChat消息路径分析及多端消息同步改造方案分享
本文为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
花了很多心思,感谢分享。

图是什么工具画的?看起来很酷炫
签名: 《零基础IM开发入门(三):什么是IM系统的可靠性?》http://www.52im.net/thread-3182-1-1.html
引用:JackJiang 发表于 2020-01-29 22:21
花了很多心思,感谢分享。

图是什么工具画的?看起来很酷炫

XMind
打赏楼主 ×
使用微信打赏! 使用支付宝打赏!

返回顶部