开源IM项目OpenIM 客户端SDK架构剖析-确保消息的有序性,以及消息百分百可达
开源IM项目OpenIM第二版对于客户端架构进行了局部重构,解决了消息触发时序等bug,也梳理了内部模块。目前已经接近尾声,本文重点讲解SDK架构,以便大家深入了解OpenIM,并希望大家能深度参与开发。很多开发者有个误区,认为IM的挑战主要在服务端,当然服务端有其挑战,包括性能、压力、时延等,但优秀的IM架构需要服务端和客户端完美配合,比如消息对齐机制,本地缓存和后台数据同步,app多端如何实时同步。
github 6.5K star 具体地址:
客户端重点问题总结:
(1)如何确保消息有序性;
(2)如何确保消息百分百可达;
(2)如果确保本地db和服务端数据的一致性;
(3)如何高效地实现多端同步;
(4)如果确保消息即时达到;
(5)消息发送的异步性,如何确保消息发送的一致性;
本文从架构角度重点解答第1,2两个问题
客户端模块划分和协程模型

WsConn:ws连接管理器。提供函数供其他方调用,具体包括:
(1)ws连接服务端,和OpenIM服务端保持长连接;
(2)关闭ws连接;
(3)通过ws发送请求;
WsRespAsyn:ws请求-响应同步器,因为ws是异步处理,需要把请求和响应关联起来,提供函数供其他方调用(消息发送,心跳发送,拉取历史消息等)
(1)getCh:为每个请求生成一个channel和msgIncr,使用map关联起来 msgIncr->channel
(2)notifyResp:对于ws收到的每个响应,通过msgIncr找到channel,并往channel发送响应,通知响应到达;
Ws:模块对WsConn 和 WsRespAsyn功能进行整合(1)请求响应同步化,提供函数SendReqWaitResp,调用者通过ws发送请求后,等待此请求的响应达到。(2)对于接收到的推送消息,把消息写入PushMsgAndMaxSeqCh channel,触发MsgSync消息同步协程。
具体实现:ReadData协程:接收服务端ws数据,并根据收到的数据类型(心跳、推送、踢出登录、拉取历史消息等),触发不同的逻辑处理,(1)对于主动发送请求的响应,则调用WsRespAsyn的notifyResp响应触发接口;(2)对于push消息,写入PushMsgAndMaxSeqCh ,触发MsgSync消息同步协程。
MsgSync:消息同步器;包含Ws 和conversationCh 、 PushMsgAndMaxSeqCh ,启动消息同步协程,对PushMsgAndMaxSeqCh 中的读取的数据做处理,具体包括:
(1)从PushMsgAndMaxSeqCh 读取服务端最大seq:SvrMaxSeq(由heartbeat写入的),对比本地最大seq:LocalMaxSeq和服务端最大seq: SvrMaxSeq,计算出缺失的seq,从服务器拉取历史消息,放入conversationCh ,触发conversation协程处理;
(2)从PushMsgAndMaxSeqCh 读取ws推送消息(由Ws的ReadData写入的推送消息),如果消息中的seq+1==LocalMaxSeq,则写入conversationCh,触发conversation处理,否则从服务端拉取消息补齐[LocalMaxSeq+1, seq],放入conversationCh ,触发conversation协程处理;
heartbeat:心跳管理器,包括MsgSync
(1)心跳协程,从服务端定时获取最大seq:SvrMaxSeq,然后把SvrMaxSeq让入PushMsgAndMaxSeqCh ,触发MsgSync消息同步协程。
心跳和消息同步融合

在心跳逻辑中触发消息同步
(1)心跳协程每30秒通过ws从服务端获取最大seq:SvrMaxSeq;
(2)心跳协程把SvrMaxSeq写入PushMsgAndMaxSeqCh ,触发MsgSync消息同步协程;
(3)MsgSync消息同步协程从PushMsgAndMaxSeqCh 中读取SvrMaxSeq,
(4)MsgSync消息同步协程对比本地最大seq: LocalMaxSeq和SvrMaxSeq,如果有缺失,则通过ws拉取历史消息,范围为:[localMaxSeq+1,SvrMaxSeq],
(6)MsgSync消息同步协程把拉取到的缺失的历史消息写入conversationCh 中;
(7)msg-conversation消息会话协程从conversationCh 中读取缺失的历史消息,按照消息类型做业务处理,具体包括消息落地本地db,触发新消息回调,触发会话改变回调(或新增回调)
push消息触发同步

以push消息触发同步:
(1)Ws的ReadData协程收到服务端的推送消息,
(2)Ws的ReadData协程把推送消息写入PushMsgAndMaxSeqCh ,触发MsgSync消息同步协程。
(3)MsgSync消息同步协程从PushMsgAndMaxSeqCh 中读取推送消息,如果msg中的seq比本地最大seq大1,则跳过第4步,直接写入conversationCh,触发conversation处理;
(4)服务端拉取消息补齐[LocalMaxSeq+1, seq],放入conversationCh ,触发conversation协程处理;
(5)以下基本与以心跳触发同步过程一样。
总结
由于seq是按照消息的客观事件递增生成的,对于推送消息,如果比本地最大seq大1,则消息可以无缝对接。否则要么推送的是过时消息,要么推送消息和本地消息有差异,需要通过ws拉取后写入本地,并触发相应回调。至此,客户端消息和服务端消息完全同步,并保证新消息回调的有序性。
重点参考我们开发文档:https://doc.rentsoft.cn/
github地址:OpenIM Corporation
开源IM项目OpenIM 客户端SDK架构剖析-确保消息的有序性,以及消息百分百可达的更多相关文章
- ASP.NET MVC WebApi 返回数据类型序列化控制(json,xml) 用javascript在客户端删除某一个cookie键值对 input点击链接另一个页面,各种操作。 C# 往线程里传参数的方法总结 TCP/IP 协议 用C#+Selenium+ChromeDriver 生成我的咕咚跑步路线地图 (转)值得学习百度开源70+项目
ASP.NET MVC WebApi 返回数据类型序列化控制(json,xml) 我们都知道在使用WebApi的时候Controller会自动将Action的返回值自动进行各种序列化处理(序列化为 ...
- 开源软件项目管理系统招设计/开发。。。。。Zend Framework2架构 svn://735.ikwb.com/pms
开源软件项目管理系统招设计/开发.....Zend Framework2架构svn://735.ikwb.com/pms
- C#开源资源项目
一.AOP框架 Encase 是C#编写开发的为.NET平台提供的AOP框架.Encase 独特的提供了把方面(aspects)部署到运行时代码,而其它AOP框架依赖配置文件的方式.这种部署方面(as ...
- 28款GitHub最流行的开源机器学习项目,推荐GitHub上10 个开源深度学习框架
20 个顶尖的 Python 机器学习开源项目 机器学习 2015-06-08 22:44:30 发布 您的评价: 0.0 收藏 1收藏 我们在Github上的贡献者和提交者之中检查了用Python语 ...
- [转]分布式文件系统FastDFS架构剖析
[转]分布式文件系统FastDFS架构剖析 http://www.programmer.com.cn/4380/ 文/余庆 FastDFS是一款类Google FS的开源分布式文件系统,它用纯C语言实 ...
- C++开源代码项目汇总
Google的C++开源代码项目 v8 - V8 JavaScript EngineV8 是 Google 的开源 JavaScript 引擎.V8 采用 C++ 编写,可在谷歌浏览器(来自 Go ...
- 《Netty5.0架构剖析和源码解读》【PDF】下载
<Netty5.0架构剖析和源码解读>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062545 内容简介 Netty 是个异步的 ...
- Android开发人员必须掌握的10 个开发工具+应该深入学习的10个开源应用项目
一.Android开发人员必须掌握的10 个开发工具 Android SDK 本身包含很多帮助开发人员设计.开发.测试和发布 Android 应用的工具,在本文中,我们将讨论 10 个最常用的工具. ...
- Google的C++开源代码项目
Google的C++开源代码项目 http://www.open-open.com/lib/view/open1413873531356.html v8 - V8 JavaScript Engin ...
- 码云上开源JAVA项目收藏
一. 个人学习项目 1. BootDo面向学习型的开源框架 (可以当做 管理台脚手架) BootDo是高效率,低封装,面向学习型,面向微服的开源Java EE开发框架. BootDo是在SpringB ...
随机推荐
- ByteHouse技术白皮书正式发布,云数仓核心技术能力首次全面解读(内附下载链接)
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 近日,<火山引擎云原生数据仓库 ByteHouse 技术白皮书>正式发布. 在数字化浪潮下,伴随着公有 ...
- Solon2 接口开发: 熟悉 Gateway
Gateway 是 Solon 框架的特殊控制器(也是Handler 的一个实现类).它通过注册收集之后,在局部范围内提供:二级路由.拦截.过滤.融断.异常处理等功能,并统一到网关处理. 另一个作用: ...
- SrpingBoot 集成 xxl-job 部署在 Docker 上碰到的坑
如果不指定 xxl.job.executor.ip,默认会用 Docker 的IP,注册到 xxl-job 里面,这时候无法回调 如果xxl.job.executor.ip.xxl.job.execu ...
- 【奥运会】yahoo的这个骚操作令人费解。。。
昨天在朋友圈发了一张截图,貌似很多朋友没有 get 到点,我也实在搞不懂 Yahoo 的这波操作. 默认排序是按照金牌总数,那必然是美国第一名了.不过习惯上不应该是按照金牌总数进行排名吗?毕竟金银铜牌 ...
- LT01 创建转储单
一.LT01创建转储单 采购订单--MIGO收货--虚拟仓位--LT01上架--实体仓位--LT01下架--虚拟仓位--MIGO发料--生产订单 二.参考代码 "-------------- ...
- 【JAVA基础】JAVA基础知识整理
https://www.weixueyuan.net/java/rumen_1/ JAVA的三大版本 JDK.JRE.JVM JAVA安装与卸载 JDK结构 HelloWorld运行 编译型与解释型 ...
- .NET 6 整合 Autofac 依赖注入容器
前言 一行业务代码还没写,框架代码一大堆,不利于学习. 常看到java的学习资料或博客,标题一般为<SpringBoot 整合 XXX>,所以仿照着写了<.NET 6 整合 Auto ...
- 【每日一题】6.Rinne Loves Edges (树形DP)
题目链接:Here 树形DP 算法讲解:Here 无向联通图其实就是树的形状,其次让我们以 s 为根使得所有的叶子节点不能到达根并且让删去边权的总和最小,那么就是典型的 树形DP 了. \(dp_i\ ...
- JS上下文和作用域链
开发中我们可能会不小心将写多个相同名称的变量,也经常会写一个递归调用的方法, 上述示例中程序执行顺序如下图,程序会按照顺序执行第一个子元素内部所有的程序,当最底层执行结束后,会逐渐抛出返回值,然后执行 ...
- 线性代数 · 矩阵 · Matlab | Moore-Penrose 伪逆矩阵代码实现
背景 - Moore-Penrose 伪逆矩阵: 对任意矩阵 \(A\in\mathbb C^{m\times n}\) ,其 Moore-Penrose 逆矩阵 \(A^+\in\mathbb C^ ...