顶层设计-IM系统架构

一、系统总体架构概览

即时通讯(IM)系统的核心目标,是让用户可以随时随地稳定地发送和接收消息。为了支撑成千上万用户同时在线交流,我们需要将整个系统划分成多个专职模块,每个模块只负责一件事情,彼此协同配合。

最基础的一层是 WebSocket 服务。WebSocket 是一种保持长连接的通信方式,可以让客户端和服务器随时互发消息。但一个 WebSocket 服务器的连接数是有限的,一般能同时维护几千个连接,因此我们通常会部署多个 WebSocket 服务实例,组成一个"集群",来支撑海量在线用户。

在 WebSocket 服务之上,还有一系列专门的服务模块:

  • IM 服务:负责消息的收发与转发,也就是把你发的消息送到对方那里。

  • Logic 服务:处理登录后的操作,比如你上线、加好友、建群,这些都归它管。

  • Auth 服务:负责登录验证,确保你是你。

  • Router 服务:像导航员一样,决定消息该送去哪台服务器上的哪个用户。

除了模块分工,IM 系统还有一个重要设计:消息一定要先保存再发出去。这保证了即使网络出问题,消息也不会丢。保存之后,系统会通过消息队列把消息交给后续处理模块继续处理,比如发送到你好友的"信箱"里。

总的来说,整个系统像流水线一样,每一步都专注做好一件事,最终让消息安全、快速地送达每一位用户手中。

二、核心服务模块介绍

整个 IM 系统就像一个团队,每个成员负责不同的工作。下面我们来看看这些"成员"都做些什么。

1. WebSocket 服务

这是系统的"入口"。每个在线用户,都会通过 WebSocket 和服务器保持一个长连接。这个连接就像一条专属通道,方便用户随时发消息、收消息。

但一个 WebSocket 服务器能撑的连接数量有限,一般几千个就到头了。所以我们会部署很多台,组成一个"集群",大家一起分担压力。

2. IM 服务

这是系统中最重要的"中转站"。

你发出一条消息后,IM 服务会先把它保存到数据库 ,然后丢进一个消息队列,再交给后面专门的模块去处理。为什么要这样?为了确保消息不会丢失,即使网络闪了一下,消息也还在。

它还负责把消息转发给接收方,比如你发了一句话给朋友,IM 服务就会负责把这句话送过去。

3. Logic 服务

Logic(逻辑)服务管的是用户行为。

比如:

  • 登录后多久没动了,要不要认为你掉线了?

  • 你加了一个好友,要不要让对方知道?

  • 创建一个群聊,拉了谁进来?

这些操作都属于"逻辑事件",由这个服务来处理。

4. Auth 服务

Auth 是认证服务,意思是"你是谁"的确认。

比如你输入账号密码登录,系统会调用 Auth 服务确认这个账号是否合法。如果你用的是第三方登录(比如微信、GitHub),Auth 也负责对接这些服务,确保只有通过验证的人才能进来。

5. Router 服务

Router(路由)服务的职责是找人。

比如你要给好友发消息,系统得先知道:他现在在哪台服务器上?连的是哪一个 WebSocket 实例?Router 服务会告诉你消息应该往哪发。

当然可以,这里是 "三、消息处理机制" 的内容,继续保持通俗、清晰、简洁的风格,面向小白讲解:

三、消息处理机制

当你在聊天窗口里按下"发送"按钮,背后其实触发了一连串操作。下面我们来看看,一条消息从你手里出去,到达对方的手里,中间到底经历了什么。

1. 消息先入库,再发送

你发的每一条消息,系统都会先保存起来,也就是"入库"。

为什么要先保存?这是为了防止消息丢失。比如你发完消息后,网络突然断了,如果没保存就直接发,很可能这条消息就彻底丢了。保存之后,就算后续出问题,也可以补发。

所以,IM 服务会:

  • 把消息写入数据库(比如 MongoDB、MySQL 等)

  • 然后告诉你:"发送成功!"

2. 消息写入队列

消息保存后,不会直接发给对方,而是先丢到一个"消息队列"中。

这个队列就像一个"中转仓库",专门用来缓冲和调度消息。这样可以让处理流程更灵活,比如根据用户在线状态、网络条件、处理能力,安排合适的时间发消息。

3. 写扩散与用户信箱

消息进入队列后,有多个"消息处理器"来处理这些消息

其中一个关键思路叫做 "写扩散",意思是:

  • 系统会主动把这条消息写到**目标用户的"信箱"**里,

  • 每个用户都有自己的消息列表(就像邮箱收件箱),

  • 登录时或收到推送时,系统会从信箱中取出消息送给你。

这样做的好处是:接收方什么时候来都能拿到消息,不怕错过。

4. 热点信箱的设计

对于一些经常聊天的热门用户(比如大 V 或群主),他们的消息非常多。

如果每个用户都维护完整的信箱,系统会变得很慢。因此我们会设计一个 "热点信箱",专门处理这类高频用户,减少重复写入,提升效率。

比如一个群有几千人,系统不需要把同一条群消息复制几千遍,而是用热点信箱+聚合机制,智能分发。

四、聚合层设计

前面说过,每个用户都有一个自己的"信箱",专门用来存放别人发给 TA 的消息。对于一些活跃用户,除了普通信箱外,还会有一个**"热点信箱"**,存放高频或群聊消息。

聚合层的作用,就是把这些分散的消息来源 统一起来,给用户呈现一份最终的收件列表

1. 为什么需要聚合层?

想象一下:

  • 一部分消息在用户自己的信箱里;

  • 一部分消息在群聊的热点信箱里;

  • 还有一些可能来自系统通知、客服等。

如果客户端要自己去找这些消息,就像你自己跑到各个邮箱、微信群、通知中心去翻,麻烦又低效。

所以,我们引入聚合层:

  • 它会自动去不同地方收集消息

  • 然后按时间顺序整理好

  • 最后一口气推送给用户。

2. 聚合层怎么工作?

流程其实不复杂:

  1. 用户上线后,客户端向聚合层请求"新消息";

  2. 聚合层会去:

    • 用户个人信箱取消息;

    • 热点信箱查是否有该用户感兴趣的群消息;

  3. 将多个来源的消息合并在一起;

  4. 排好顺序,按页返回给用户。

这样一来,用户只需要调一次接口,就能拿到所有需要的消息,既快又省资源。

3. 推模式 vs 拉模式

聚合层支持两种方式:

  • 拉模式:客户端主动问"有没有新消息?"

  • 推模式:系统检测到有新消息,直接通知客户端来取。

实际使用时,两者会配合起来使用,确保消息不漏、不慢、不中断

五、可靠推送与 ACK 策略

在 IM 系统中,"消息已送达"不代表"对方已经收到"。为了确保消息真正到达用户手里,并且对方确实收到了,系统需要一套可靠推送机制 ,其中一个关键环节就是 ACK(应答确认)

1. 什么是 ACK?

ACK 是英文 Acknowledgement 的缩写,意思是"确认"。

举个例子:你给朋友发了一条消息,系统通过 WebSocket 把消息推到了朋友的手机上,这时候朋友的设备会给服务器回一个"我收到了"的信号,这个信号就是 ACK。

只有服务器收到这个 ACK,才说明消息真正送达了客户端。

2. 为什么需要 ACK?

如果没有 ACK,系统根本不知道消息有没有送到。可能你朋友网络不通、手机掉线,甚至消息被系统中的某个节点"弄丢了",这些都需要系统感知并做补救。

所以,ACK 有两个核心作用:

  • 确认送达:保证用户真的收到了消息。

  • 触发下一步逻辑:比如更新"消息状态",从"已发送"变成"已送达"。

3. 如果没有收到 ACK 怎么办?

系统会设置一个超时时间,比如 5 秒。如果超过这个时间还没收到 ACK,就认为"推送失败"。

这时候系统可能会:

  • 重试推送:再次把消息发一遍。

  • 切换推送通道:如果 WebSocket 不通,可以尝试发离线推送(比如通知栏提示)。

  • 记录失败状态:方便后续排查或提醒用户"消息可能没送达"。

4. ACK 的流程总结一下:

  1. 服务器把消息推送到客户端

  2. 客户端收到消息,立刻回 ACK

  3. 服务器收到 ACK,标记消息为"送达成功"

  4. 如果长时间没收到 ACK,就重试或记录失败

相关推荐
seabirdssss19 分钟前
使用Spring Boot DevTools快速重启功能
java·spring boot·后端
喂完待续28 分钟前
【序列晋升】29 Spring Cloud Task 微服务架构下的轻量级任务调度框架
java·spring·spring cloud·云原生·架构·big data·序列晋升
benben04430 分钟前
ReAct模式解读
java·ai
文火冰糖的硅基工坊41 分钟前
[光学原理与应用-433]:晶体光学 - 晶体光学是研究光在单晶体中传播规律及其伴随现象的分支学科,聚焦于各向异性光学媒质的光学特性
系统架构·光学·激光器·跨学科融合
轮到我狗叫了1 小时前
牛客.小红的子串牛客.kotori和抽卡牛客.循环汉诺塔牛客.ruby和薯条
java·开发语言·算法
yudiandian20141 小时前
【QT 5.12.12 下载 Windows 版本】
开发语言·qt
高山有多高1 小时前
详解文件操作
c语言·开发语言·数据库·c++·算法
狂奔的sherry2 小时前
单例模式(巨通俗易懂)普通单例,懒汉单例的实现和区别,依赖注入......
开发语言·c++·单例模式
Volunteer Technology2 小时前
三高项目-缓存设计
java·spring·缓存·高并发·高可用·高数据量
EnigmaCoder2 小时前
【C++】引用的本质与高效应用
开发语言·c++