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层对数据的获取需求。

目录
相关文章
|
2月前
|
存储 算法 安全
微信团队分享:来看看微信十年前的IM消息收发架构,你做到了吗
好的架构是迭代出来的,却也少不了良好的设计,本文将带大家回顾微信背后最初的也是最核心的IM消息收发技术架构,愿各位读者能从中获得启发。
97 1
|
2月前
|
运维 Linux Apache
LAMP架构调优(三)——模块的安装与调用
LAMP架构调优(三)——模块的安装与调用
14 0
|
2月前
|
存储 NoSQL Redis
陌陌技术分享:陌陌IM在后端KV缓存架构上的技术实践
在本文中,陌陌数据库负责人冀浩东将聚焦探讨陌陌的 KV 系统架构选型思路,深入解析如何进行此类系统的甄选决策,同时进一步分享陌陌团队在采用 OceanBase(OBKV)过程中所经历的探索与实践经验。
63 0
|
11月前
|
运维 监控 网络协议
【运维知识进阶篇】集群架构-Nginx常用模块(目录索引+状态监控+访问控制+访问限制)(下)
【运维知识进阶篇】集群架构-Nginx常用模块(目录索引+状态监控+访问控制+访问限制)(下)
65 0
|
11月前
|
运维 监控 应用服务中间件
【运维知识进阶篇】集群架构-Nginx常用模块(目录索引+状态监控+访问控制+访问限制)(上)
【运维知识进阶篇】集群架构-Nginx常用模块(目录索引+状态监控+访问控制+访问限制)
76 0
|
2月前
|
消息中间件 缓存 开发工具
一套分布式IM即时通讯系统的技术选型和架构设计
为了更好的理解分布式IM即时通讯系统的设计,我站在架构师的角度,在充分了解系统需求、业务流程和技术流程后,从全局视角为系统设定方案目标,对技术方案进行选型,对系统进行总体架构设计和分层架构设计,并梳理清楚发送消息的交互链路、单聊和群聊的交互链路。希望对你有帮助。
269 0
|
9月前
|
存储 监控 数据库
揭秘企业微信是如何支持超大规模IM组织架构的——技术解读四维关系链
本文将摘取企业微信的其中一个技术分支——IM体系之下的“关系链”内核要素,为你揭秘企业微信是如何支持超大规模IM组织架构的。
71 0
|
11月前
|
消息中间件 前端开发 Java
Springboot+WebSocket 实现IM及时通讯
项目中碰到需要及时通讯的场景,使用springboot集成websocket,即可实现简单的及时通讯。本文介绍springboot如何集成websocket、IM及时通讯需要哪些模块、开发和部署过程中遇到的问题、以及实现小型IM及时通讯的代码。
|
10月前
|
消息中间件 存储 RocketMQ
即时通讯技术文集(第20期):IM架构设计技术文章(Part3) [共14篇]
为了更好地分类阅读 52im.net 总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第20 期。
77 0
|
10月前
|
存储 自然语言处理 容灾
即时通讯技术文集(第19期):IM架构设计基础知识合集 [共13篇]
为了更好地分类阅读 52im.net 总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第19 期。
67 0