开源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架构剖析-确保消息的有序性,以及消息百分百可达的更多相关文章

  1. 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的返回值自动进行各种序列化处理(序列化为 ...

  2. 开源软件项目管理系统招设计/开发。。。。。Zend Framework2架构 svn://735.ikwb.com/pms

    开源软件项目管理系统招设计/开发.....Zend Framework2架构svn://735.ikwb.com/pms

  3. C#开源资源项目

    一.AOP框架 Encase 是C#编写开发的为.NET平台提供的AOP框架.Encase 独特的提供了把方面(aspects)部署到运行时代码,而其它AOP框架依赖配置文件的方式.这种部署方面(as ...

  4. 28款GitHub最流行的开源机器学习项目,推荐GitHub上10 个开源深度学习框架

    20 个顶尖的 Python 机器学习开源项目 机器学习 2015-06-08 22:44:30 发布 您的评价: 0.0 收藏 1收藏 我们在Github上的贡献者和提交者之中检查了用Python语 ...

  5. [转]分布式文件系统FastDFS架构剖析

    [转]分布式文件系统FastDFS架构剖析 http://www.programmer.com.cn/4380/ 文/余庆 FastDFS是一款类Google FS的开源分布式文件系统,它用纯C语言实 ...

  6. C++开源代码项目汇总

    Google的C++开源代码项目 v8  -  V8 JavaScript EngineV8 是 Google 的开源 JavaScript 引擎.V8 采用 C++ 编写,可在谷歌浏览器(来自 Go ...

  7. 《Netty5.0架构剖析和源码解读》【PDF】下载

    <Netty5.0架构剖析和源码解读>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062545 内容简介 Netty 是个异步的 ...

  8. Android开发人员必须掌握的10 个开发工具+应该深入学习的10个开源应用项目

    一.Android开发人员必须掌握的10 个开发工具 Android SDK 本身包含很多帮助开发人员设计.开发.测试和发布 Android 应用的工具,在本文中,我们将讨论 10 个最常用的工具. ...

  9. Google的C++开源代码项目

    Google的C++开源代码项目 http://www.open-open.com/lib/view/open1413873531356.html v8  -  V8 JavaScript Engin ...

  10. 码云上开源JAVA项目收藏

    一. 个人学习项目 1. BootDo面向学习型的开源框架 (可以当做 管理台脚手架) BootDo是高效率,低封装,面向学习型,面向微服的开源Java EE开发框架. BootDo是在SpringB ...

随机推荐

  1. 火山引擎ByteHouse:云原生数据库如何提升MySQL兼容性?

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 当前各类软件层出不穷,单独某一款软件往往难以满足企业应用需求,一般都需要与各类软件组合使用,这时软件生态兼容性就显 ...

  2. 火山引擎DataLeap如何解决SLA治理难题(一):应用场景与核心概念介绍

    更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 基于火山引擎分布式治理的理念,数据平台数据治理团队自研了火山引擎DataLeap SLA保障平台,目前已在字节内部 ...

  3. 基于jdk自带httpserver开发的最小完整MVC框架

    基于jdk自带httpserver开发的最小完整MVC框架 410kb级的完整MVC:solon(83k) + jdkhttp(27k) + enjoy(227k) + snack3(73k) DEM ...

  4. Hyper-V CentOS Linux 硬盘扩容

    同一物理盘进行扩容(非挂载),首先在虚机内将硬盘空间扩大, Hyper-V 需要将检查点删除 查看物理卷和卷组,并将物理卷加入到卷组 #将剩余空间添加到逻辑卷 /dev/centos/root lve ...

  5. 愉快的了解Charles

    charles是PC端常用的网络封包截取工具,在做移动开发时,我们为了调试与服务器端的网络通讯协议,常常需要截取网络封包来分析.除了在做移动开发中调式端口外,charles也可以用于分析第三方应用的通 ...

  6. 我“采访”了 ChatGPT

    我"采访"了 ChatGPT 大家好,我是准备认真码字的**老章:. 最近ChatGPT火的爆表,看了很多相关文章,特别焦虑,唯恐自己的进步赶不上 AI 的发展. 还有就是我非常看 ...

  7. 接口文档 token发展史 jwt介绍和原理 drf-jwt快速使用

    目录 昨日回顾 认证 权限 频率 全局异常处理 接口文档 接口文档编写 drf自动生成接口文档 cookies-session-token发展史 jwt介绍和原理 jwt的构成 base64的编码和解 ...

  8. PDF转图片-itextpdf-java源码

    提供PDF 文件转图片的工具类. 电子签章过程中存在着在网页上对签署文件进行预览.指定签署位置.文件签署等操作,由 于图片在浏览器上的兼容性和友好性优于PDF 文件,所以一般在网页上进行电子签章时,会 ...

  9. Optional详细用法

    package com.example.apidemo.jdk8; import com.example.apidemo.vo.UserInfo; import java.math.BigDecima ...

  10. mybatis-plus Date类型的参数 只有年月日 没有时分秒的解决办法

    问题: 使用mybatis-plus 设计实体的时候 使用   Date inTime;   数据库里的时间2021-11-05 22:00:13 但java里的时间变成了2021-11-05 00: ...