1000W长连接,如何建立和维护?千万用户IM 架构设计
在40岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格,遇到很多很重要的架构类/设计类的场景题:
1.千万用户规模 IM 架构设计,请说出你的方案?
2.1000万长连接,如何建立和维护?
最近有小伙伴在面试 美团,又遇到了 IM 架构问题。小伙伴支支吾吾的说了几句,面试挂了。
所以,尼恩给大家做一下系统化、体系化的梳理,使得大家内力猛增,可以充分展示一下大家雄厚的 "技术肌肉",让面试官爱到 "不能自已、口水直流",然后实现"offer直提"。
当然,这道面试题,以及参考答案,也会收入咱们的 《尼恩Java面试宝典PDF》V171版本,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。
最新《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请关注本公众号【技术自由圈】获取,回复:领电子书
一、IM的重大价值
1、IM的广泛使用场景:
即时通信(Instant Messaging,简称 IM)是一种通过网络进行实时通信的系统,允许用户之间快速传递信息。
无论是文字消息、文件,还是语音和视频交流,IM 系统都能即时响应。
即时通信(IM)功能模块具有广泛的应用场景,可以集成到多种系统中,以增强沟通和协作能力。
以下是一些常见的即时通信(IM)应用场景:
1. 企业内部沟通系统
- 协作工具:如 Slack、Microsoft Teams 等,为团队提供即时消息、文件共享、视频会议等功能,提升工作效率。
- 企业管理系统(ERP、CRM):整合 IM 功能,方便员工快速交流、协作,以及与客户或合作伙伴沟通。
2. 社交平台
- 社交网络:如 Facebook、Twitter 等,可以通过 IM 功能让用户私下交流或创建群组讨论。
- 在线社区和论坛:提供用户之间的即时消息功能,增强互动性和用户粘性。
3. 电子商务平台
- 客户支持:如 Shopify、Amazon 等电商平台,通过 IM 实现客户与客服的实时沟通,解决售前咨询或售后服务问题。
- 买卖双方沟通:买家与卖家可以直接通过 IM 沟通,协商交易细节。
4. 教育系统
- 在线学习平台:如 Coursera、Udemy,师生之间可以通过 IM 进行实时交流,辅导和答疑。
- 校园管理系统:学校内部系统中,师生或学生之间可以通过 IM 进行联系,安排活动或布置作业。
5. 医疗系统
- 远程医疗:患者与医生之间可以通过 IM 进行初步沟通,预约咨询或远程诊断。
- 医院管理系统:医院内部工作人员之间可以通过 IM 实时沟通,协调工作和安排。
6. 在线游戏
- 多人在线游戏:如 MMORPG、MOBA 类游戏,通过 IM 实现玩家之间的实时沟通和策略讨论。
- 游戏社交平台:玩家之间可以通过 IM 进行交流、组队或分享游戏经验。
7. 金融系统
- 在线银行和支付系统:如支付宝、微信支付,通过 IM 功能实现用户与客服的沟通,解决支付问题或账户管理。
- 投资和交易平台:投资者之间或与金融顾问之间通过 IM 进行市场讨论和交易建议交流。
这些 IM 功能模块能够融入不同系统,极大地提升了用户的交互体验和系统的服务能力。
2、IM的巨大学习价值:
由于IM的广泛使用场景广泛,所以im的学习价值巨大。
另外,im也是面试的重点和难点。
3、技术要点:
1)、网络传输协议:
IM系统传输即时消息无外乎使用UDP、TCP、基于TCP的HTTP这几种协议中的一种或几种
- UDP协议实时性更好,但是如何处理安全可靠的传输并且处理不同客户端之间的消息交互是个难题,实现起来过于复杂;
- HTTP协议属于扩展支持,数据传输量大;
- TCP协议如果有海量用户的需求。如何保证单机服务器高并发量,如何做到灵活,扩展的架构。
2)、数据通信格式(协议)
- 自定义二进制:信息体积小,占用带宽低,传输效率高,缺点是处理不同客户端之间的消息交互较复杂。
- 提供序列化和反序列化库的开源协议:protocol buffers, json, Thrift。是一种流行的通用数据格式,扩展相当方便,序列化和反序列化相当方便。
- 文本化协议:序列化,反序列化容易(库支持),可视化强;缺点:相对于二进制存储占用体积大
3)、如何保证实时消息的有序性、可用性
- IM中消息的投递中要保证发送方发送顺序与接收方展现顺序一致。
- IM中如何保证在线实时消息的可靠投递,即消息的不丢失和不重复。
- TCP 自带TCP Keepalive 无法满足需求。
4)、如何处理群发消息以及离线消息
5)、如何进行消息持久化
6)、如何避免数据中心级故障?
二:10万用户->100万用户->1000万用户 的架构演进
10万用户 | 100万用户 | 1000万用户 | |
---|---|---|---|
存储架构 | MySQL 主备Redis 主备 | MySQL 主备 Redis cluster MongoDB | MySQL 主备 Redis cluster HBASE存储平台 |
接入架构 | 2台 Nginx 负载均衡 | 2台 Nginx/LVS 负载均衡三级缓存 | 2台 Nginx/LVS 负载均衡三级缓存 / 多数据中心部署 |
可扩展架构 | 2个单体架构/直连 | 3个服务微服务/异步广播 | 3个服务微服务/异步精准路由 |
高可用 | MySQL 主备跨机房复制,只保证基础数据不丢失 | 同城双中心 | 同城双活/异地双活 |
大数据架构 | MongoDB | 大数据平台 flink + ES+ HBASE | |
基础设施 | 快速扩展(辅助需求) | 全面完善(基础技术) |
三:10万用户im架构
1、多协议支持
支持TCP、WebSocket。使用 Netty 和 Protobuf 实现高性能IM 通信模块,能够结合 Netty 的高性能网络通信框架和 Protobuf 的高效序列化机制,构建一个高效、可扩展的即时通信系统。
要构建一个高性能的 IM 通信模块,使用 Netty 和 Protobuf 并支持 TCP 和 WebSocket 协议,需要设计一个能够处理多种协议、灵活扩展、并且能够保证低延迟和高吞吐量的架构。
-
TCP 通信:
- ChannelPipeline 配置 :通过 Netty 的
ChannelPipeline
配置解码器(ProtobufDecoder)、编码器(ProtobufEncoder)和自定义的ChannelHandler
。 - TCP Server :通过
ServerBootstrap
启动 TCP 服务,绑定端口并监听连接。
- ChannelPipeline 配置 :通过 Netty 的
-
WebSocket 通信:
-
HTTP 协议升级:首先通过 HTTP 进行握手,然后升级为 WebSocket 协议。
Netty 提供了
WebSocketServerProtocolHandler
来处理协议升级。 -
消息处理:在升级为 WebSocket 后,使用 WebSocketFrame 来传递消息,再通过 Protobuf 进行编解码。
-
WebSocket Server :与 TCP 类似,使用
ServerBootstrap
启动并配置 WebSocket 服务。
-
2. 消息编解码设计
消息编解码:利用 Protobuf 进行消息的序列化和反序列化,减少数据传输的大小,并保证高效的数据传输。
- Protobuf 生成器 :通过
.proto
文件定义消息结构,并使用protoc
编译生成相应的 Java 类。 - Protobuf 编解码:
- ProtobufDecoder:将收到的二进制数据解码为 Protobuf 消息对象。
- ProtobufEncoder:将消息对象编码为二进制格式,准备发送。
3. 用户管理与消息路由
- 用户连接管理 :
- 使用数据结构(如
ConcurrentHashMap
)来管理用户的连接映射,跟踪每个用户的Channel
实例。 - 使用redis 来管理 user 和node 的映射关系,跟踪每个用户的 node 实例。
- 多设备支持:如果一个用户可以有多个设备在线,需要设计一个映射来跟踪每个设备的连接。
- 使用数据结构(如
- 消息路由与分发 :
- 实现消息的路由逻辑,根据接收者的 ID 查找对应的
Channel
并将消息发送。 - 支持单播、组播(群聊)和广播消息。
- 实现消息的路由逻辑,根据接收者的 ID 查找对应的
4. 心跳机制
- TCP 心跳 :通过 Netty 的
IdleStateHandler
检测连接的空闲状态,如果超过一定时间没有读写操作,可以发送心跳包或断开连接。 - WebSocket 心跳:使用 WebSocket 的 PING/PONG 帧来维持连接活跃状态。
5.高可用性设计:
实现服务的集群化部署,使用 ZooKeeper 等工具进行服务注册和发现,保证集群的高可用性。
6)扩展性与容错性设计
-
分布式架构:
im 服务实例可以水平扩展,设计 Router 服务,实现im 服务实例 直接的 负载均衡。
-
负载均衡架构:
同时可以把im节点分组,通过ng负载均衡,保证 接入层的高可用性。
7)10万用户im架构与实操
10万用户im架构与实操, 具体请参考尼恩的IM实操视频。
四:100万用户im架构,如何进行升级?
1、高扩展架构:功能的细粒度、分布式解耦
在构建高性能 IM 系统时,将不同的功能模块解耦是一个关键的设计策略,可以提高系统的可维护性、可扩展性和容错能力。
通过将 IM 服务拆分为多个独立的微服务,每个服务专注于特定的功能模块,能够更好地分配资源、隔离故障并简化开发和部署流程。
使im服务node的不同功能模块解耦,如连接管理服务、业务逻辑服务等。
连接管理服务职责:
- 管理用户的长连接,处理 TCP 和 WebSocket 连接的建立与断开。
- 维护用户的在线状态,管理链接的 heartbeat 心跳。
- 连接管理服务可以组成集群,每个连接管理节点可以维护一部分用户的连接(分片管理),并通过一个注册中心(如 ZooKeeper)来协调和管理节点间的负载。
logic 业务逻辑 服务 包括:
- 消息处理服务
- 用户认证服务
- 群组管理
- 聊天记录管理
- 消息过滤等。
2、基于Rocketmq做异步消息推送
1. 架构设计
- 生产者-消费者模型:IM 系统的消息生产者(如发送消息的客户端或服务)将消息推送到 Rocketmq主题中,消费者(如消息接收者的客户端或服务)从 Rocketmq中拉取消息进行处理。
- 分区与副本:Rocketmq主题可以分为多个分区,分区内的消息是有序的;同时,为了实现高可用性,每个分区可以有多个副本,分布在不同的 Rocketmqbroker 上。
2. 消息生产
- 消息队列设计:根据业务需求,设计 Rocketmq主题的分区策略。例如,可以按照用户 ID 或聊天会话 ID 来进行分区,以保证相关消息的有序性。
- 消息格式:设计消息的序列化格式(如 JSON、Avro、Protobuf),并确保消息内容包括必要的元数据,如消息 ID、时间戳、发送者和接收者 ID。
3. 消息消费
- 消费者组:接收消息的消费者可以被组织为一个消费者组,Rocketmq会将主题的分区分配给消费者组内的不同消费者,确保每个分区的消息只被一个消费者处理,避免重复消费。
- 消费确认与偏移量管理:消费者在处理消息后,需要提交消费偏移量(Offset)到 Kafka,以便在重启或故障恢复时从正确的位置继续消费。可以选择自动提交(自动提交可能有消息丢失的风险)或手动提交(需要在消息处理完成后手动提交,保证消息处理的准确性)。
4. 消息持久化与顺序性
- 消息持久化:Rocketmq自带持久化机制,消息可以保留一定时间(可配置),即使消费者临时不可用,消息也不会丢失。
- 消息顺序:如果需要保证消息的顺序性,可以将相关消息(如同一会话中的消息)发送到同一分区中。
5. 故障处理与重试机制
- 消息重试:在消息处理失败时,可以将消息重新放回 Rocketmq队列或记录到专用的失败队列,进行后续重试或人工处理。
- 幂等性处理:在消费端实现幂等性逻辑,确保消息即使被多次处理也不会引发不一致问题。
3、100万用户im架构总体架构
4、ConnectManager服务:用户代理服务器,用于客户端的连接
- 客户端首先连接到
ConnectManager
服务,`ConnectManager 发送消息到 rocketmq 。
2)logic 业务逻辑 服务 收到消息,进行 消息的处理
3)如果是收到登录的消息,logic 校验用户的合法性
-
如果 校验通过,logic 会返回一个 token 给 rocketmq , 这是一个广播消息, 该 token 成为该连接的安全通讯的令牌
-
ConnectManager 收到令牌,标识登录成功,并且给客户端正确的响应, 后面可以开始正常的聊天消息处理,
-
客户端接下来可以发心跳包给
ConnectManager
,ConnectManager 会转发到 rocketmq , logic 业务逻辑处理心跳包。
7) 客户端发送消息给ConnectManager ,ConnectManager 会转发到 rocketmq , logic 业务逻辑 服务 将MQ
的消息处理完成后, 处理结果发送到 rocketmq ,ConnectManager 再将其转发到对应的客户端。
8) 这里的rocketmq 下行消息是广播模式, 同一个下行的消息,会发送给所有的ConnectManager ,ConnectManager 收到属于当前节点的回复消息,再将其转发到对应的客户端,如果 收到消息不是当前节点的消息,ConnectManager 抛弃。
5、logic 业务逻辑 服务:主要业务处理模块
1)、订阅rocketmqmq,处理Comet对Logic的远程RPC调用的处理,如用户登录注册等。
2)、启用rest 服务,监听business 微服务上 B端推送的IM的消息,将这些聊天相关的业务发生到 Kafka。
6、100万用户im架构中的跨node的会话路由
1)这里,分为local-session 本地会话 、Distrubute-session 分布式会话。
其中,local-session使用map来维护本地会话。分布式session 使用redis 维护全局的会话映射关系,分布式会话映射关系清晰,但是模式比较重。
100万用户im, 其实使用 local-session 本地会话 ,其实就可以了。跨node的会话路由,通过Rocketmq做广播消息解决。
2)跨node的会话路由,100W连接的场景,可以简单的使用的事件广播,由各节点自行判断是否持有local-session 会话。
3)当然,当有1000W级链接, node节点较多时,所有节点均被广播,资源浪费。
跨node的会话路由 整体流程如下:
1)客户端与网关的任何一个ConnectManager节点建立长连接,节点会将其加入到内存中的长连接队列。客户端会定期向服务端发送心跳消息,若超过设定时间还未收到心跳,则认为客户端与服务端的长连接已断开,服务端会关闭连接,清理内存中的会话。
2)当业务系统需要向客户端推送数据时,通过提供的HTTP接口将数据发送至服务 logic服务 。
3) logic服务 在收到推送请求后,服务会将消息写入RocketMQ。
4)ConnectManager 服务作为消费者,以广播模式消费消息,所有ConnectManager 节点都能收到消息。
5)ConnectManager节点在收到消息后会判断推送的消息目标是否在其内存 local-session map中维护的长连接队列里,如果存在则通过长连接推送数据,否则直接忽略。
7、100万用户的数据存储架构
- 存储平台
1.SQL 平台;2.NoSQL 平台;3.文件存储。
- 大数据平台
1.离线处理;2.在线处理;3.推荐系统。
这里的NoSQL 平台 使用MongoDB, 具体的架构方案与实操,请参见:
100亿级数据存储架构:MYSQL双写 + HABSE +Flink +ES综合大实操
五:1000万用户im架构,如何再造升天?
1、高扩展架构:更进一步的 功能的细粒度解耦, 实现无限可扩展的架构
在构建1000w用户高性能 IM 系统时,将不同的 logic 功能模块解耦是一个关键的设计策略,可以提高系统的可维护性、可扩展性和容错能力。
通过将logic 服务拆分为多个独立的微服务,每个服务专注于特定的功能模块,能够更好地分配资源、隔离故障并简化开发和部署流程。
logic 业务逻辑 服务负责:
-
消息处理服务
-
消息过滤等。
UserAuth 服务负责:
- 用户认证服务
group 服务负责:
- 群组管理
storage 服务负责:
- 聊天记录管理
其他服务负责:
- 风控等等。
不同的服务,使用不同的消费者group:
- 消费者组:接收消息的消费者可以被组织为一个消费者组,Rocketmq会将主题的分区分配给消费者组内的不同消费者,确保每个分区的消息只被一个消费者处理,避免重复消费。
- 消费确认与偏移量管理:消费者在处理消息后,需要提交消费偏移量(Offset)到 Kafka,以便在重启或故障恢复时从正确的位置继续消费。可以选择自动提交(自动提交可能有消息丢失的风险)或手动提交(需要在消息处理完成后手动提交,保证消息处理的准确性)。
2、1000万用户im架构中的跨node的会话路由
在处理大规模连接和高并发的场景时,跨节点的会话路由是一个关键的技术挑战。
1000万用户 , 跨node的会话路由,通过Rocketmq做广播消息,会造成网络资源浪费。
这里需要用到 Rocketmq集群消息 + Distrubute-session 分布式会话。
1)这里,使用 Distrubute-session 分布式会话。
local-session使用map来维护本地会话。但这里还要结合 使用 分布式session 使用redis 维护全局的会话映射关系,分布式会话映射关系清晰,但是模式比较重。
2)跨node的会话路由,1000W连接的场景,可以采用的 Rocketmq集群消息 ,每个节点的消息,发到这个节点对应的topic。
3) Rocketmq Topic设计:
- 为每个节点创建一个独立的Topic,确保消息可以定向发送到正确的节点。
- 考虑使用分区(Partition)来提高并发处理能力。
4) Producer 设计:
- 可以根据会话ID或其他业务标识符,来确定node 对应的topic。
- 配置Producer 以发送消息到正确的Topic。
5) Consumer配置设计:
-
每个node 节点上的Consumer订阅对应的Topic。
-
根据业务需求配置并发数量和消费策略。
3)、如何避免数据中心级故障?
数据中心级故障 故障的原因很多,比如:
在 IM 系统中实现异地多活(Active-Active)架构,并确保消息数据同步,是为了提高系统的可用性和容灾能力,同时降低网络延迟对用户体验的影响。
异地多活意味着多个数据中心在不同的地理位置同时提供服务,这些数据中心之间需要保持数据的一致性,尤其是消息数据的同步。以下是实现异地多活架构及消息数据同步的关键点和设计策略。
- 异地多活(Active-Active) 架构设计原则
- 全局分布式架构:将 IM 系统部署在多个地理位置不同的数据中心,每个数据中心都能够独立处理用户的连接和消息,但所有数据中心之间需要实现高效的数据同步和一致性保障。
- 数据分区与路由:可以根据用户的地理位置将其连接路由到离用户最近的数据中心,减少网络延迟。同时,系统需要能够处理跨数据中心的消息传递。
- 高可用性和容错性:任何一个数据中心的故障不应该影响整体服务的可用性,其他数据中心应当能够无缝接管业务。
- 异地多活(Active-Active) 数据同步机制
-
消息队列同步:使用分布式消息队列(Rocketmq)在数据中心之间传递消息。每个数据中心的消息队列, 设置sync-Storage 微服务,负责将本地消息复制到其他数据中心,保证消息的一致性。
-
数据库同步:
使用分布式数据库(如 Cassandra、CockroachDB)或数据库复制技术(如 MySQL 的 GTID 复制、主从复制)来实现数据同步。
这里采用了方式1: 每个数据中心 设置sync-Storage 微服务,负责将本地消息复制到其他数据中心,保证消息的一致性。
4、1000万用户的数据存储架构
- 存储平台
1.SQL 平台;2.NoSQL 平台;3.文件存储。
- 大数据平台
1.离线处理;2.在线处理;3.推荐系统。
这里的NoSQL 平台 使用 hbase, 具体的架构方案与实操,请参见:
100亿级数据存储架构:MYSQL双写 + HABSE +Flink +ES综合大实操
说在最后:有问题找老架构取经
1000万长连接,如何建立和维护?
千万用户IM 架构设计 ?
以上的内容,如果大家能对答如流,如数家珍,基本上 面试官会被你 震惊到、吸引到。
最终,让面试官爱到 "不能自已、口水直流"。offer, 也就来了。
在面试之前,建议大家系统化的刷一波 5000页《尼恩Java面试宝典PDF》,里边有大量的大厂真题、面试难题、架构难题。
很多小伙伴刷完后, 吊打面试官, 大厂横着走。
在刷题过程中,如果有啥问题,大家可以来 找 40岁老架构师尼恩交流。
另外,如果没有面试机会,可以找尼恩来改简历、做帮扶。
遇到职业难题,找老架构取经, 可以省去太多的折腾,省去太多的弯路。
尼恩指导了大量的小伙伴上岸,前段时间,刚指导一个40岁+被裁小伙伴,拿到了一个年薪100W的offer。
狠狠卷,实现 "offer自由" 很容易的, 前段时间一个武汉的跟着尼恩卷了2年的小伙伴, 在极度严寒/痛苦被裁的环境下, offer拿到手软, 实现真正的 "offer自由" 。
另外,尼恩也给一线企业提供 《DDD 的架构落地》企业内部培训,目前给不少企业做过内部的咨询和培训,效果非常好。
尼恩技术圣经系列PDF
- 《NIO圣经:一次穿透NIO、Selector、Epoll底层原理》
- 《Docker圣经:大白话说Docker底层原理,6W字实现Docker自由》
- 《K8S学习圣经:大白话说K8S底层原理,14W字实现K8S自由》
- 《SpringCloud Alibaba 学习圣经,10万字实现SpringCloud 自由》
- 《大数据HBase学习圣经:一本书实现HBase学习自由》
- 《大数据Flink学习圣经:一本书实现大数据Flink自由》
- 《响应式圣经:10W字,实现Spring响应式编程自由》
- 《Go学习圣经:Go语言实现高并发CRUD业务开发》
......完整版尼恩技术圣经PDF集群,请找尼恩领取
《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》PDF,请到下面公号【技术自由圈】取↓↓↓