IM通讯模块架构设计

简介: 一些在设计IM通讯模块时的架构经验

前言

IM模块承载着复杂功能,需要提供通讯支持,数据支持,以及页面的支持。随着项目的进度推进,业务信令,以及数据类型会增加的非常快,对业务功能的快速响应尤为重要。

UI模块

思路可以沿用MVVM的思路,通过VM来驱动UI的更新,通过实现不同的VM协议来制定不同的UI展示规则。

需要注意的是尽量避免相似业务维护这多套代码。比如单选用户转发消息,多选用户创建群聊,从群员列表选择用户操作,这几个业务就存在相似的业务逻辑,区别可能在不同的数据源,不同的选择逻辑,不同的数据验证逻辑。这样就可以通过抽象ViewModel的方法,来共用一套UI选择展示界面。

通讯/数据模块

多使用协议来抽象功能模块逻辑,方便后期支持多种业务。比如,数据接收器的功能逻辑大致相同,启用的逻辑也大致相同,那么使用协议实现可以更容易的维护逐渐增多的接收器;

为功能模块提供插件注入口,通过加载不同的插件,使新功能在原有逻辑中也能生效,而不需要修改原有逻辑。比如,消息信令的处理,只需实现不同的消息信令处理插件,并注册到消息接收器中,新的信令协议就可以生效。

IM业务存在高并发的场景,在设计通讯/数据模块时,需要预先规划下线程的使用,避免后期由于线程资源问题引起的性能瓶颈。

UI模块设计

UI层的模块设计需要注意高并发情况下的性能优化。

比如在接收高流量的消息的时,如聊天详情页面很容易陷入瓶颈。

  1. 渲染频次过高会导致主线程阻塞,比如复杂的聊天气泡,会导致App卡顿,可以设计异步串型队列来限流高并发状态下的渲染频次。
  2. 不必要的在主线程的数据库操作也会造成主线程阻塞,可以通过缓存减少查询次数,也可以改为异步执行。
  3. 加载过多的资源,会导致App OOM,特别是对数据库资源的占用(Realm有这个问题)会有额外的资源消耗,需要制定合适的资源释放逻辑,来保证内存的占用情况,自动释放池也可以解决一些简单的内存管理问题。

通讯/数据模块设计

网络层

TCP连接管理模块(IMSocket)

IM最先要做的是建立与服务端的Socket链接,我选用了GCDAsyncSocket作为底层来搭建整个TCP管理模块。

  1. 网络状态监控使用AFNetworkReachabilityManager,需要根据网络状态来执行TCP的断连或者重连。
  2. 实现Socket的连接状态维护,当Socket连接状态变化时,发送通知。
  3. 提供Socket的配置API,方便后期做环境切换。
  4. 根据通信协议生成用于发送的数据包,并对包体内容进行AES加密。
  5. 接收到数据后,对数据进行预处理,先判断数据是否粘包,对数据包进行拆包。待包完整后,对数据进行AES解密。
  6. 心跳策略,根据不同的网络选择不同的心跳间隔。

TCP请求管理模块(IMEngine、IMRequestDispatcher)

完成TCP连接后,需要实现TCP的请求管理,如维护AskId,公共请求参数配置。

  1. 通过AskId维护请求与接收响应的回调。实现只响应一次的回调以及可多次响应可手动注销的回调。
  2. 接入protocol buffer与服务端定义通信协议。
  3. 实现基于protocol buffer的请求协议与响应协议,定义每个请求的请求类型,以及响应时用哪个模型解析数据。
  4. 实现请求超时逻辑与请求取消逻辑。

IM请求管理模块(IMConnectAssistant、IMHTTPAssistant)

对TCP、HTTP请求进行封装管理,配置公共请求参数,管理连接的重试逻辑。

  1. 在请求的生命周期中,增加注入口,方便业务使用时有更多的时机可以选。例如,在请求构造完成且未发送时,提供修改请求参数的回调。
  2. 维护请求的生命周期状态,如等待发起,发起中,完成响应,被取消等。
  3. 维护请求队列,当请求失败后,记录下请求,根据策略放入重试队列。

长链接通知分发模块(IMNotificationAssistant)

处理基于IM协议的长链接回调,对响应进行识别处理,根据内容通知不同的模块触发动作,比如新消息提醒,会话配置变更通知。

为通知分发模块开一个并行队列,但需要限制队列的最大并发数,防止高并发时线程爆炸。

TCP消息通信协议(TCPMessage,HTTPRequest)

实现与服务端PB协议的TCP请求封装,与服务器的HTTP请求封装。

数据层

IM状态管理模块(IMManager)

主要负责网关鉴权流程,IM登录流程,IM用户信息管理,注册其他模块等。

  1. 实现网关鉴权逻辑,IM服务心跳包管理。
  2. 实现IM登录逻辑,登录失败后重连逻辑,Socket中断后重连逻辑。
  3. 实现用户注销逻辑,用户数据清理逻辑。
  4. 配置用户数据库,注册数据集合观察器。

举例:比如当用户的token变化时,需要重新链接IM。当网络出现抖动时,需要开启IM登录重试。当用户完成IM登录时,需要拉取离线消息,群组信息等。

IM数据库(IMDB)

我选用的是Realm作为数据库框架,数据集合的更新通知挺好用。

  1. 保证一人一库,实现用户数据隔离。
  2. 维护IM相关业务的数据模型管理。
  3. 维护数据库迁移。
  4. 维护数据库连接池。

模型与扩展(Model、Extension)

管理IM相关的数据模型,比如消息、会话、用户、群组等。

Model的Extension默认分为3个部分,Attributes、Database、Factory。

  1. Attrubtes用于类属性的扩展,如判断消息是否属于加密类型,会话是否属于群组会话等。
  2. Database用于数据库CRUD的扩展,如获取未读消息数,查询会话中的关联消息等。
  3. Factory用于模型特定形式的构建,如构建文件分享的消息,根据用户创建聊天回话等。

数据接收器(IMDataFetcher)

使用协议实现IM数据的获取逻辑,分为主动获取与被动通知获取两种形式,包含HTTP与TCP API。

  1. 维护接收器的获取状态。
  2. 注册通知接收器,如当发生群组列表更新时,新消息提醒时,触发数据接收动作。
  3. 为存在高并发场景的数据接收器增设任务队列。当队列空闲时,直接触发任务。当队列繁忙时,任务会进入队列等待,由定时器触发任务。另外获取消息这样的API存在重复性,堆积在任务队列中请求所能响应的数据时相同的,所以当定时器触发任务时,可以将失效的任务直接丢弃处理,避免重复请求。

消息处理器(IMMessageProcesser)

抽象接收消息逻辑,统一处理业务方提供的多条消息通道。

不同通道对消息的处理有所不同,需要提供功能插件,在消息完成模型构建和校验后,对消息进行处理。

举例:分包消息则对消息进行转存处理,撤回消息指令则直接执行后丢弃指令消息等。

数据集合监听器(IMDBObserver)

通过数据库通知自动触发,承担了大部分的数据更新需求。

  1. 这里用到了Realm的特性,Realm可以根据规则指定一个数据集合,比如所有isRead为False的未读消息集合。当数据集合中的发生数据新增,数据修改,数据删除时,均能通知给注册者。
  2. 我们对特定数据集合进行监听,当数据集合发生变化时,触发预设操作。比如,有新消息入库时,触发对应会话的最近消息属性更新。当群组信息(名称)变更时,触发对应会话的属性更新。
  3. 为存在高并发情况的DBObserver创建任务队列。当集合的更新频率过高时,也将任务存入队列,使用定时器限制任务并发量。

举例:当消息处理器将新消息入库后,监听器会获取到新消息,并判断是否需要更新对应会话,是否出发消息提醒,是否根据消息的类型来执行不同的任务。

模型数据源(IMDBSource)

主要用于为UI层提供数据。

  1. DBSource中配置了数据集合,数据集合的监听器,监听器的回调代理,监听器的回调线程。
  2. 监听器代理包含了数据CUD,UI层通过实现监听器代理,即可实现数据驱动的显示模式。

举例:在聊天详情页面,分页获取消息数据。当有新消息入库时,通过DBSource通知UI层进行更新。

封装UI层对数据的获取需求。

目录
相关文章
|
28天前
|
机器学习/深度学习 自然语言处理 搜索推荐
大厂 10Wqps智能客服平台,如何实现架构演进?
40岁老架构师尼恩,凭借深厚的架构功力,指导众多小伙伴成功转型大模型架构师,实现职业逆袭。尼恩的《LLM大模型学习圣经》系列PDF,从基础理论到实战应用,全面覆盖大模型技术,助力读者成为大模型领域的专家。该系列包括《从0到1吃透Transformer技术底座》《从0到1吃透大模型的基础实操》《从0到1吃透大模型的顶级架构》等,内容详实,适合不同水平的读者学习。此外,尼恩还分享了多个智能客服平台的实际案例,展示了大模型在不同场景中的应用,为读者提供了宝贵的实践经验。更多技术资料和指导,请关注尼恩的《技术自由圈》公众号。
大厂 10Wqps智能客服平台,如何实现架构演进?
|
1月前
|
存储 安全 开发工具
百度公共IM系统的Andriod端IM SDK组件架构设计与技术实现
本文主要介绍了百度公共IM系统的Andriod端IM SDK的建设背景、IM SDK主要结构和工作流程以及建设过程遇到的问题和解决方案。
53 3
|
28天前
|
消息中间件 网络协议 NoSQL
1000W长连接,如何建立和维护?千万用户IM 架构设计
最近有小伙伴在面试 美团,又遇到了 IM 架构问题。小伙伴支支吾吾的说了几句,面试挂了。 所以,尼恩给大家做一下系统化、体系化的梳理,使得大家内力猛增,可以充分展示一下大家雄厚的 “技术肌肉”,**让面试官爱到 “不能自已、口水直流”**,然后实现”offer直提”
|
2月前
|
编解码 Linux 开发工具
Linux平台x86_64|aarch64架构RTMP推送|轻量级RTSP服务模块集成说明
支持x64_64架构、aarch64架构(需要glibc-2.21及以上版本的Linux系统, 需要libX11.so.6, 需要GLib–2.0, 需安装 libstdc++.so.6.0.21、GLIBCXX_3.4.21、 CXXABI_1.3.9)。
|
3月前
|
网络协议 Java 物联网
MQTT(EMQX) - SpringBoot 整合MQTT 连接池 Demo - 附源代码 + 在线客服聊天架构图
MQTT(EMQX) - SpringBoot 整合MQTT 连接池 Demo - 附源代码 + 在线客服聊天架构图
761 2
|
5月前
|
前端开发 JavaScript 架构师
Webpack模块联邦:微前端架构的新选择
Webpack的模块联邦是Webpack 5引入的革命性特性,革新了微前端架构。它允许独立的Web应用在运行时动态共享代码,无需传统打包过程。基本概念包括容器应用(负责加载协调)和远程应用(独立应用,可暴露模块)。实现步骤涉及容器和远程应用的`ModuleFederationPlugin`配置,以及在应用间导入和使用远程模块。模块联邦的优势在于独立开发、按需加载、版本管理和易于维护。通过实战案例展示了如何构建微前端应用,包括创建容器和远程应用,以及消费远程组件。高级用法涉及动态加载、路由集成、状态管理和错误处理。
95 3
|
5月前
|
监控 Java 关系型数据库
java版MES系统源码,后端采用 Spring Boot 多模块架构
MES系统采用Vue3的vue-element-plus-admin为后台,Spring Boot多模块架构,支持MySQL、Oracle等数据库,具备SaaS多租户功能。核心功能包括车间计划排程、工艺流程配置、生产质量管理、进度追踪、库存和排班管理等,全面覆盖生产运营关键环节。
java版MES系统源码,后端采用 Spring Boot 多模块架构
|
4月前
|
监控
交易平台---架构设计第一步拆分模块,拆分为7个模块
交易平台---架构设计第一步拆分模块,拆分为7个模块
|
6月前
|
存储 算法 安全
微信团队分享:来看看微信十年前的IM消息收发架构,你做到了吗
好的架构是迭代出来的,却也少不了良好的设计,本文将带大家回顾微信背后最初的也是最核心的IM消息收发技术架构,愿各位读者能从中获得启发。
228 1
|
6月前
|
运维 Linux Apache
LAMP架构调优(三)——模块的安装与调用
LAMP架构调优(三)——模块的安装与调用
32 0