分类: 云计算
2023-03-16 14:03:01
如何设计一款高性能、高并发、高可用的im综合消息平台是很多公司发展过程中会碰到且必须要解决的问题。比如一家公司内部的通讯系统、各个互联网平台的客服咨询系统,都是离不开一款好用且维护的方便im综合消息系统。那么,我们应该怎么样来设计一款三高特性的im系统,并能同时支持各个业务线的接入(比如:内部OA通讯、客服咨询、消息推送等等功能)有呢?
m{BANNED}中国第一版设计的初衷是公司需要一款im消息中间件用于支撑客服咨询业务。
但是,考虑到为了方便日后其他业务线也能接入消息沟通平台,所以一开始就将整个消息中心的能力需求给到中间件团队进行开发,以便除客服外的各业务线接入综合消息中心,从而实现多元的消息实时触达能力。
1)存储端:
在初版的架构下,存储端我们使用tidb、redis作为主要存储:
[1] redis用于存储消息已读未读,缓存连接信息等功能;
[2] tidb作为开源的分布式数据库,选择它是为了方便消息的存储。
2)mq消息总线:
我们使用rocketmq来实现消息总线(PS:即分布式情况下,不同im实例间通过MQ进行消息交互)。
消息总线是整个im的核心,使用rocketmq能支持十万级别的tps。基本所有服务都要从消息总线中消费消息进行业务处理。
3)zookeeper注册中心:各个服务会注册到zk中,方便服务之间内部进行调用,同样也可以暴露服务给外部进行调用。
4)link服务:
link服务主要用于接收客户端的ws(WebSocket协议)、tcp、udp等协议的连接。
同时调用用户服务进行认证,并投递连接成功的消息给位置服务进行消费,存储连接信息。
ws(WebSocket协议)过来的消息先到link再投递到消息总线。
5)消息分发服务:
消息分发服务主要用于接收消息总线推过来的消息进行处理,按照im内部消息协议构造好消息体后,又推送到消息总线中(比如会推给会话服务、消息盒子、link服务)。
6)位置服务:
存储link的(WebSocket协议)连接、tcp连接等信息,并使用redis进行缓存(key为userId),方便根据UserId查询到该用户所登录的客户端连接在哪个link上。
一个用户在相同设备只能登录一个,但可以支持多端登录。即时通讯聊天软件app开发可以加小蓝豆的v:weikeyun24咨询
7)用户服务:用于存储所有用户,提供认证查询接口。
8)消息盒子:存储所有消息,提供消息查询、消息已读未读、消息未读数、消息检索等功能。
9)会话服务:管理会话、群聊会话、单聊会话等功能。
在上节的架构设计介绍中,我们详细分享了初版IM系统架构的设计思路以及具体流程。
那么在初版IM架构设计中还存在什么样的问题,又该如何优化呢?我们一条条来看看。
3.1 使用MQ消息总线的问题
正如上节所分享的那样,我们初版IM架构中,link服务到消息分发服务的消息使用的MQ消息总线。
初版架构设计中,link服务将消息下推给消息分发服务进行处理时,使用的是mq消息总线(通俗了说,IM集群内不同IM实例间的通信是依赖于MQ进行的消息传递),而mq消息总线必然做对有一定的时延(而且时延受制于MQ本身的系统实现和技术策略)。
举个例子:
当两个处于不同IM实例的客户端A和B聊天时,A用户发送消息到link --> 消息总线 --> 消息分发服务 --> 消息总线 --> link --> B用户。
正如上面这个例子,im消息投递流程太长了,并且这样也会大大降低系统的吞吐量。
3.2 消息落库为写扩散的问题
其实现阶段我们使用的是跟微信一样的写扩散策略。
那么为啥微信使用写扩散不是缺陷,而对于我们的IM架构来说确是缺陷呢?