一套分布式IM即时通讯系统的技术选型和架构设计

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 为了更好的理解分布式IM即时通讯系统的设计,我站在架构师的角度,在充分了解系统需求、业务流程和技术流程后,从全局视角为系统设定方案目标,对技术方案进行选型,对系统进行总体架构设计和分层架构设计,并梳理清楚发送消息的交互链路、单聊和群聊的交互链路。希望对你有帮助。

本文由冰河分享,作者博客 binghe.gitcode.host,原题“这套分布式IM即时通讯系统如何写到简历上?我给你整理好了!”,本文有修订和改动。

1、引言
分布式IM即时通讯系统本质上就是对线上聊天和用户的管理。

针对聊天本身来说,最核心的需求就是:发送文字、图片、文件、语音、视频、消息缓存、消息存储、消息未读、已读、撤回,离线消息、历史消息、单聊、群聊,多端同步,以及其他一些需求。

对用户管理来说,存在的需求包含:添加好友、查看好友列表、删除好友、查看好友信息、创建群聊、加入群聊、查看群成员信息、退出群聊、修改群昵称、拉人进群、踢人出群、解散群聊、填写群公告、修改群备注以及其他用户相关的需求等。

为了更好的理解分布式IM即时通讯系统的设计,我站在架构师的角度,在充分了解系统需求、业务流程和技术流程后,从全局视角为系统设定方案目标,对技术方案进行选型,对系统进行总体架构设计和分层架构设计,并梳理清楚发送消息的交互链路、单聊和群聊的交互链路。希望对你有帮助。

技术交流:

(本文已同步发布于:http://www.52im.net/thread-4564-1-1.html)

2、方案目标
在进行技术选型与总体架构设计之前,需要明确一个事项,就是系统无论采用哪种方案,采用哪种架构设计都需要明确这种方案的业务目标、技术目标和架构目标,并在研发过程中不断评估系统的总体性能表现,发现系统瓶颈并不断进行优化。

总体上,我们搭建和开发的分布式IM即时通讯系统,需要满足如下方案目标。

具体是:

1)业务目标:满足需求设计篇章中的各类需求场景;
2)技术目标:支持无限扩容,百万用户同时在线聊天;
3)架构目标:高并发、高性能、高可用、可监控、可预警、可伸缩,支持无限扩展。
3、技术选型
在技术选型上,除了采用SpringBoot等基础框架外,也会采用容器化方案。

同时,考虑到为了尽量降低技术门槛,在整个分布式IM即时通讯系统的技术选型中,主要采用市面上比较流行的技术框架和方案。

具体选型如下所示:

1)开发框架:SpringBoot、SpringCloud、SpringCloud Alibaba、Dubbo;
2)缓存:Redis分布式缓存+Guava本地缓存;
3)数据库:MySQL、TiDB、HBase;
4)流量网关:OpenResty+Lua;
5)业务网关:SpringCloud Gateway + Sentinel;
6)持久层框架:MyBatis、Mybatis-Plus;
7)服务配置、服务注册与发现:Nacos;
8)消息中间件:RocketMQ;
9)网络通信:Netty;
10)文件存储:Minio;
11)日志可视化治理:ELK;
12)容器化管理:Swarm、Portainer;
13)监控:Prometheus、Grafana;
14)前端:Vue;
15)单元测试:Junit;
16)基准测试:JMH;
17)压力测试:JMeter。
4、初步架构设计
对于IM即时通讯系统来说,涵盖了即时通讯后端服务、大后端平台、SDK接入服务、OpenAI接入服务、大前端UI,我相信不少小伙伴多多少少能够画出IM即时通讯系统的架构图,大致如下图所示。

其实,这种这种架构设计也比较常见,在这种架构设计中,Kong/Openresty/Nginx只做负载均衡和反向代理,研发人员更多的是关注业务层和基础层的开发,流量比较小时,这种架构设计一般不会有什么问题。但是一旦流量比较大,用户调用后端平台的接口发送消息时,即时通讯SDK同步调用即时通讯服务的接口就会出现性能问题。

因为每个终端同时只能与一个IM即时通讯服务实例建立连接,如果大量的用户终端恰好都与一个IM即时通讯服务建立连接,那即时通讯SDK频繁同步调用同一个IM即时通讯服务的接口就会出现性能瓶颈。此时,出现性能瓶颈时,不仅仅会影响到IM即时通讯服务,也会对后端平台接收请求的业务造成一定的影响。

5、架构设计优化
既然上节图中所示的架构设计存在性能瓶颈,那我们如何进行优化呢?

为此我们在前图基础上进行了优化,优化后的架构如下图所示。

对比两图可以看出,在屏蔽掉技术实现细节的前提下,我们将对业务的校验和流量管控进行前置化,放大Kong/OpenResty/Nginx的职责,使得这些软件不仅具备反向代理和负载均衡的功能,还能实现限流、黑白名单、流量管控、业务校验等功能。

也就是说,在这种架构模式下,我们充分发挥了整个分布式IM即时通讯系统的入口职责,充分利用Kong/OpenResty/Nginx的高并发、高吞吐量的能力,尽量将大部分无效请求挡在整个系统之外。例如,用户在没登录系统的前提下,就尝试调用发送消息、添加好友、添加群组等等接口。这样会大大减轻后台平台的业务压力。

除了在Kong/OpenResty/Nginx中实现限流、黑白名单、流量管控、业务校验等功能外,我们还引入了业务网关集群,实现限流、降级、熔断、流控、校验、鉴权等功能,进一步保证下游系统的稳定性和安全。

为了解决大量用户终端恰好连接到同一个IM即时通讯服务实例,IM即时通讯SDK频繁调用同一个IM即时通讯服务实例的接口造成的性能问题。我们在IM即时通讯服务SDK与IM即时通讯服务之间引入了RocketMQ集群。

IM即时通讯服务集群中的每一个IM即时通讯服务实例在集群中都有一个唯一的ID,并且每个IM即时通讯服务实例在启动后,只会监听RocketMQ中与自身ID相关的Topic。这样每个IM即时通讯服务只会收到与自身ID相关的Topic中的消息,不会接收所有的消息。

当用户登录系统后,就会与IM即时通讯服务建立长连接,并且会以用户ID和终端为Key,以IM即时通讯服务的ID为value,将其存储到分布式缓存中。同时,会以用户ID和终端为Key,以用户终端与IM即时通讯服务建立的长连接为value,将其存储到IM即时通讯服务本地内存中。

当用户调用后端平台的接口发消息时,会带上目标用户的ID,并且在IM即时通讯SDK中会指定用户登录的终端设备,最终会通过IM即时通讯SDK向RocketMQ发送消息。

此时IM即时通讯SDK会根据目标用户ID和终端从分布式缓存中获取目标用户连接的IM即时通讯服务的ID,并向此ID相关的Topic发送消息。此时与目标用户建立长连接的IM即时通讯服务就会接收到RocketMQ中的消息,随后根据用户ID和终端从本地缓存中获取到与用户终端建立的长连接,并基于此长连接向用户推送消息。

另外,在实际实现中,为了避免大量用户同时只连接IM即时通讯服务集群中的某一个服务实例,会对用户连接的IP、浏览器指纹、手机设备等做Hash和取模运算,使其尽量均匀分布到集群中的每一个服务实例上。

那么问题来了,这种架构设计还有进一步优化的空间吗?

6、容器化架构设计
为进一步增强分布式IM即时通讯系统的性能、可用性和弹性伸缩能力,我们可以对分布式IM即时通讯系统进行容器化架构设计,如下图所示。

可以看到,我们对分布式IM即时通讯系统的架构设计进行了进一步优化,采用了容器化架构设计。在原有架构的基础上,我们进行了如下改进和优化。

1)基础支撑服务:基础支撑服务会由各种基础中间件、数据存储服务、以及监控服务实现,包含:MySQL数据库、TiDB数据库、HBase、Redis缓存、RocketMQ消息队列、Prometheus监控和Portainer容器管理等基础中间件实现,基础支撑服务会对整个分布式IM即时通讯系统提供最基础的数据、传输、监控和容器管理等服务。

2)容器化:在容器化层面,会通过Docker、Swarm和Portainer实现,其中,会基于Swarm和Portainer对容器化进行管理。

3)其他基础性功能实现:除了上述分层架构外,对于建设分布式IM即时通讯系统来说,还要考虑异常监控、服务注册与发现、可视化、服务降级与兜底数据、服务限流、服务容灾、容量规划与扩缩容和全链路压测等。

7、DDD分层业务架构设计
在分布式IM即时通讯系统中,不管是大后端平台,还是IM即时通讯服务,我们都会对业务层的代码采用分层业务架构。

这里,可以借鉴DDD的分层架构思想,将代码总体上分成展示层、应用层、领域层和基础设施层四个层次。

但是,考虑到分布式IM即时通讯系统的特殊性,又不会严格按照DDD的原则来设计代码分层,具体按照如下图所示。

可以看到,分布式IM即时通讯系统会借鉴DDD的设计思想,但是不会完全按照DDD的方式进行设计。

1)展示层:展示层,也叫做用户UI层,是DDD设计的最上层,对外提供API接口,接收客户端请求,解析参数,返回结果数据,并对异常进行处理。

2)应用层:应用层,也叫做Application层,应用层主要处理容易变化的业务场景,可对相关的事件、调度和其他聚合操作进行相关的处理。

3)领域层:领域层,也叫做Domain层,领域层可以说是DDD设计的精髓所在,它是将业务系统中相对不变的部分抽象出来封装成领域模型。在分布式IM即时通讯系统的设计中,领域层基本不会依赖其他层,也不会依赖基础设施层,这里是与DDD设计存在区别的地方。

4)基础设施层:基础设施层,也叫做Infrastructure层,基础设施层会对其他各层提供通用的基础能力,在分布式IM即时通讯系统中,就包括了缓存、通用工具类、消息、系统的持久化机制等。

8、总体IM消息交互链路
在分布式IM即时通讯系统中,我们忽略掉其他一些细节信息,重点关注下发送消息的交互链路逻辑。不管是单聊还是群聊,最终都需要通过IM即时通讯服务将消息推送给用户的终端。此时发送消息的流程如下图所示。

可以看到:用户在分布式IM即时通讯系统发送消息时,不管是单聊还是群聊,最终的消息都会推送到用户登录的终端设备上。假设此时用户A给用户B发送消息,或者用户A和用户B在同一个群组,用户A向群组发送消息,用户B接收消息的主要流程如下。

具体是:

1)用户A调用后端平台的接口向用户B发送消息,并且发送的消息中会带有用户B的ID以及终端信息;
2)后端平台将消息缓存起来,并且会将消息异步写入消息库;
3)后端平台从Redis中获取用户B连接的IM即时通讯服务的ID;
4)后端平台获取到用户B连接的IM即时通讯服务的ID后,会向RocketMQ中用户B连接的IM即时通讯服务ID对应的Topic发送消息;
5)IM即时通讯服务会监听自身服务ID对应的RocketMQ中Topic的消息,此时,用户B连接的IM即时通讯服务会接收到消息;
6)IM即时通讯服务接收到消息后,会根据用户B的ID以及终端信息从缓存中获取用户B与IM即时通讯服务建立的连接,并且通过这个连接向用户B推送消息。
要实现如上发送消息的流程,前提是要满足如下条件:

1)后端平台满足分布式条件,可随时横向扩展;
2)IM即时通讯服务满足分布式条件,可随时横向扩展;
3)每个启动的IM即时通讯服务实例在集群中都有一个唯一的ID;
4)每个IM即时通讯服务,都只监听自身ID对应的RocketMQ中Topic的消息;
5)用户登录分布式IM即时通讯系统后,会与IM即时通讯服务建立长连接,并且会根据用户ID和所在的终端缓存长连接,同时会根据用户ID和所在的终端将连接的IM即时通讯服务的ID缓存到Redis;
6)用户发送消息时,会根据目标用户的ID和终端从Redis中获取IM即时通讯服务的ID,进而向当前IM即时通讯服务的ID对应的RocketMQ的Topic发送消息;
7)对应的IM即时通讯服务监听并接收到RocketMQ消息后,会根据目标用户的ID和终端从缓存中获取到用户的连接信息,向目标用户推送消息。
9、IM单聊交互链路
单聊就是在分布式IM即时通讯系统中,一个用户直接与另外一个用户聊天,也就是一对一的聊天。在这种场景下,很有可能单聊的两个用户中,出现用户不在线的情况。

例如:用户A给用户B发送消息时,用户B可能不在线。

此时,我们就需要将用户A向用户B发送的消息存储起来。

其实,在我们实现的分布式IM即时通讯系统中,无论把用户B是否在线,都会存储消息记录。当用户B登录系统后,将消息同步给用户B,如下图所示。

可以看到,用户A向用户B发送消息时:

1)如果用户B在线,就可以按照发送消息的交互链路向用户B发送消息了;
2)如果用户B不在线,此时就无法向用户B正常推送消息。当用户B登录分布式IM即时通讯系统后,就会调用后端平台的接口拉取所有未读消息,并通过用户B在线流程向用户B推送消息。
10、IM群聊交互链路
群聊就是在分布式IM即时通讯系统中,多个用户在同一个群组中进行聊天。

此时在发送消息时,我们可以通过群组ID找出群内所有在线的用户,将消息即时发送给在线的用户。

那些未在线的用户就按照单聊未在线的用户进行处理,如下图所示。

可以看到,群聊的交互链路流程如下所示:

1)用户调用后端平台的接口向群组发送消息;
2)后端平台将消息缓存并异步写入消息库;
3)由于是向群组发送消息,群里有多个用户,此时就会从Redis中获取所有用户连接的IM即时通讯服务ID列表;
4)对用户按照服务ID分组,将相同服务ID下的用户分在同一个逻辑分组里,方便后续推送消息,并且会记录未在线的用户列表;
5)循环向每个服务ID对应的RocketMQ中的Topic发送消息;
6)广播处理未在线用户的未读消息ID;
7)IM即时通讯服务会监听自身服务ID对应的Topic,会随时接收推送到自身服务的消息;
8)当IM即时通讯服务接收到消息后,此时用户掉线,或者用户不在线,向用户推送消息就会失败,或者未查询到用户与IM即时通讯服务建立的连接,就不会向用户推送消息;
9)当用户登录分布式IM即时通讯系统后,会从后端平台拉取历史(离线)消息,并通过用户在线的流程,向用户推送消息;
好了,看到这里,你明白如何设计一个高度可扩展的分布式IM即时通讯系统了吗?

11、相关资料
[1] 浅谈IM系统的架构设计

[2] 简述移动端IM开发的那些坑:架构设计、通信协议和客户端

[3] 一套海量在线用户的移动端IM架构设计实践分享(含详细图文)

[4] 一套原创分布式即时通讯(IM)系统理论架构方案

[5] 移动端IM中大规模群消息的推送如何保证效率、实时性?

[6] 一套亿级用户的IM架构技术干货(上篇):整体架构、服务拆分等

[7] 一套亿级用户的IM架构技术干货(下篇):可靠性、有序性、弱网优化等

[8] 从新手到专家:如何设计一套亿级消息量的分布式IM系统

[9] 企业微信的IM架构设计揭秘:消息模型、万人群、已读回执、消息撤回等

[10] 融云技术分享:全面揭秘亿级IM消息的可靠投递机制

[11] 阿里IM技术分享(三):闲鱼亿级IM消息系统的架构演进之路

[12] 基于实践:一套百万消息量小规模IM系统技术要点总结

[13] 跟着源码学IM(十):基于Netty,搭建高性能IM集群(含技术思路+源码)

[14] 一套十万级TPS的IM综合消息系统的架构实践与思考

[15] 得物从0到1自研客服IM系统的技术实践之路

[16] 海量用户IM聊天室的架构设计与实践

[17] 史上最通俗Netty入门长文:基本介绍、环境搭建、动手实战

[18] 新手入门:目前为止最透彻的的Netty高性能原理和框架架构解析

[19] 写给初学者:Java高性能NIO框架Netty的学习方法和进阶策略

[20] 手把手教你用Netty实现网络通信程序的心跳机制、断线重连机制

[21] 史上最强Java NIO入门:担心从入门到放弃的,请读这篇!

(本文已同步发布于:http://www.52im.net/thread-4564-1-1.html)

目录
相关文章
|
1月前
|
机器学习/深度学习 自然语言处理 搜索推荐
深度分析 | 2024主流的智能客服系统有哪些?他们是怎么实现的?
本文深入探讨了智能客服系统的使用方法和相关技术实现逻辑,涵盖前端交互、服务接入、逻辑处理、数据存储四大层面,以及自然语言处理、机器学习、语音识别与合成、数据分析与挖掘、知识库管理和智能推荐系统等核心技术,帮助企业更好地理解和应用智能客服系统,提升服务效率和客户满意度。
194 1
|
14天前
|
存储 Prometheus Cloud Native
分布式系统架构6:链路追踪
本文深入探讨了分布式系统中的链路追踪理论,涵盖追踪与跨度的概念、追踪系统的模块划分及数据收集的三种方式。链路追踪旨在解决复杂分布式系统中请求流转路径不清晰的问题,帮助快速定位故障和性能瓶颈。文中介绍了基于日志、服务探针和边车代理的数据收集方法,并简述了OpenTracing、OpenCensus和OpenTelemetry等链路追踪协议的发展历程及其特点。通过理解这些概念,可以更好地掌握开源链路追踪框架的使用。
68 41
|
6天前
|
存储 消息中间件 小程序
转转平台IM系统架构设计与实践(一):整体架构设计
本文描述了转转IM为整个平台提供的支撑能力,给出了系统的整体架构设计,分析了系统架构的特性。
29 10
|
1天前
|
存储 分布式计算 Hadoop
基于Java的Hadoop文件处理系统:高效分布式数据解析与存储
本文介绍了如何借鉴Hadoop的设计思想,使用Java实现其核心功能MapReduce,解决海量数据处理问题。通过类比图书馆管理系统,详细解释了Hadoop的两大组件:HDFS(分布式文件系统)和MapReduce(分布式计算模型)。具体实现了单词统计任务,并扩展支持CSV和JSON格式的数据解析。为了提升性能,引入了Combiner减少中间数据传输,以及自定义Partitioner解决数据倾斜问题。最后总结了Hadoop在大数据处理中的重要性,鼓励Java开发者学习Hadoop以拓展技术边界。
18 7
|
1天前
|
人工智能 自然语言处理 搜索推荐
年度评选 | 2024年客服系统6大品牌
在2024年的客服系统市场中,合力亿捷等服务商品牌展现了各自在技术研发、产品创新和行业应用等方面的卓越实力。
19 1
|
1天前
|
存储 关系型数据库 分布式数据库
[PolarDB实操课] 01.PolarDB分布式版架构介绍
《PolarDB实操课》之“PolarDB分布式版架构介绍”由阿里云架构师王江颖主讲。课程涵盖PolarDB-X的分布式架构、典型业务场景(如实时交易、海量数据存储等)、分布式焦点问题(如业务连续性、一致性保障等)及技术架构详解。PolarDB-X基于Share-Nothing架构,支持HTAP能力,具备高可用性和容错性,适用于多种分布式改造和迁移场景。课程链接:[https://developer.aliyun.com/live/253957](https://developer.aliyun.com/live/253957)。更多内容可访问阿里云培训中心。
[PolarDB实操课] 01.PolarDB分布式版架构介绍
|
13天前
|
安全 UED
IM系统在体育直播网站中的重要性
IM(即时通讯)系统在体育直播平台中至关重要,提升用户体验、促进社交互动和增强平台活跃度。它支持实时互动、增强观赛氛围、构建社交网络、推送即时信息、创造商业价值并提供多元化互动体验。高并发性能、实时稳定性和用户安全是实现的关键。通过集成IM系统,平台能更好地满足观众互动需求,提升运营效益。 代码示例展示了如何在比赛数据响应中设置比赛ID、游戏ID、系列赛ID等基本信息,并检查是否有计划和关注标记。
|
24天前
|
设计模式 存储 算法
分布式系统架构5:限流设计模式
本文是小卷关于分布式系统架构学习的第5篇,重点介绍限流器及4种常见的限流设计模式:流量计数器、滑动窗口、漏桶和令牌桶。限流旨在保护系统免受超额流量冲击,确保资源合理分配。流量计数器简单但存在边界问题;滑动窗口更精细地控制流量;漏桶平滑流量但配置复杂;令牌桶允许突发流量。此外,还简要介绍了分布式限流的概念及实现方式,强调了限流的代价与收益权衡。
66 11
|
26天前
|
设计模式 监控 Java
分布式系统架构4:容错设计模式
这是小卷对分布式系统架构学习的第4篇文章,重点介绍了三种常见的容错设计模式:断路器模式、舱壁隔离模式和重试模式。断路器模式防止服务故障蔓延,舱壁隔离模式通过资源隔离避免全局影响,重试模式提升短期故障下的调用成功率。文章还对比了这些模式的优缺点及适用场景,并解释了服务熔断与服务降级的区别。尽管技术文章阅读量不高,但小卷坚持每日更新以促进个人成长。
49 11
|
28天前
|
消息中间件 存储 安全
分布式系统架构3:服务容错
分布式系统因其复杂性,故障几乎是必然的。那么如何让系统在不可避免的故障中依然保持稳定?本文详细介绍了分布式架构中7种核心的服务容错策略,包括故障转移、快速失败、安全失败等,以及它们在实际业务场景中的应用。无论是支付场景的快速失败,还是日志采集的安全失败,每种策略都有自己的适用领域和优缺点。此外,文章还为技术面试提供了解题思路,助你在关键时刻脱颖而出。掌握这些策略,不仅能提升系统健壮性,还能让你的技术栈更上一层楼!快来深入学习,走向架构师之路吧!
61 11

热门文章

最新文章