LinkX Blog

深入 LinkX 的技术实现:系统架构、模块划分,以及消息从发送到实时送达的完整链路。

架构概览

LinkX 采用前后端分离的三层架构:展现层(客户端 / 管理端)通过 HTTP 与 WebSocket 接入后端,服务层由 Spring Boot 单体承载业务逻辑,数据层使用 MySQL、Redis 与 MinIO 分别负责持久化、缓存与文件存储。

展现层

linkx-client(Electron + Vue 3)与 linkx-admin(Vue 3 管理后台)负责用户交互与界面渲染。

接入层

HTTP REST :8080/api 处理业务请求;Netty WebSocket :8081/ws 负责实时推送。

服务层

认证鉴权、IM 核心、好友群组、文件网盘、风控审计等模块统一部署在 linkx-server。

数据层

MySQL 存储业务数据,Redis 缓存 Token 与在线状态,MinIO 存储图片与文件对象。

展现层          接入层                 服务层                    数据层
─────────      ─────────────        ──────────────           ─────────────
linkx-client → HTTP  :8080/api  →  Spring Boot 3.5    →   MySQL 8.4
linkx-admin  → WS    :8081/ws   →  Netty WebSocket    →   Redis 7.2
                                    MyBatis-Flex             MinIO
                                    Flyway 迁移

模块组成

模块 技术栈 职责
linkx-client Vue 3 · Electron 33 · Pinia 单聊/群聊 UI、WebSocket 客户端、WebRTC 通话、文件网盘
linkx-admin Vue 3 · Vite · ECharts RBAC 权限、内容审核、风控策略、统计大屏
linkx-server Spring Boot 3.5 · Netty · MyBatis-Flex REST API、消息路由、在线状态、对象存储对接

服务端按业务域划分 Controller / Service / Mapper,消息写入 MySQL 后通过 Netty 通道推送给在线用户。管理端与客户端共享同一套后端 API,权限通过 JWT + RBAC 隔离。

通信通道

LinkX 刻意将「请求-响应」与「实时推送」拆分为两条通道,兼顾可靠性与低延迟。

通道 地址 典型场景
HTTP REST /api 登录注册、拉取历史消息、好友/群聊管理、文件上传
WebSocket /ws 新消息推送、已读回执、在线状态、通话/会议信令
设计原则

历史消息与分页查询走 HTTP,保证可重试与幂等;实时事件走 WebSocket,减少轮询开销。客户端登录成功后两条通道同时可用。

消息发送流程

用户发送一条聊天消息时,链路如下:

  1. 客户端将消息封装为 REST 请求(文本、图片元数据或文件引用),携带 Access Token 调用 POST /api/message/send
  2. 服务端校验 Token、会话权限与敏感词,将消息持久化至 MySQL,并生成全局唯一 messageId。
  3. 若消息含附件,文件已预先上传至 MinIO,消息体仅保存对象 key 与元数据。
  4. 持久化成功后,服务端通过 Netty 将消息事件推送给会话内在线成员(单聊对方、群聊全体成员)。
  5. 发送方客户端收到 HTTP 响应后更新本地消息状态(发送中 → 已发送),并等待对端已读回执。
用户输入 → 客户端 REST 发送 → 服务端鉴权 & 落库
                              ↓
                    Netty 推送给在线接收方
                              ↓
              接收方 WebSocket 收到 → UI 渲染新消息

实时推送机制

客户端登录后自动建立 WebSocket 长连接,并在 Header 或首帧携带 JWT 完成鉴权绑定。

连接生命周期

  • 建立连接:登录成功 → 连接 ws://host:8081/ws → 服务端将 Channel 与用户 ID 绑定。
  • 心跳保活:客户端定时发送 ping,服务端响应 pong,超时未心跳则断开并清理在线状态。
  • 断线重连:网络波动时客户端指数退避重连,重连后通过 HTTP 增量拉取离线期间的消息。

推送事件类型

  • NEW_MESSAGE — 新聊天消息
  • MESSAGE_READ — 已读回执
  • ONLINE_STATUS — 好友上线/下线
  • CALL_SIGNAL — 音视频通话信令

多端同步与离线消息

同一账号可在多台设备同时登录。每条消息以服务端时间戳与 messageId 排序,各端通过增量同步保持一致。

在线同步

任一在线设备收到 WebSocket 推送后,其他在线设备同样会收到推送(多端同时响铃/展示)。已读状态变更也会广播到所有在线端。

离线补全

设备离线期间的消息保存在 MySQL。重新连接后,客户端调用 GET /api/message/sync?since={lastMessageId} 拉取增量,合并入本地会话列表,再恢复 WebSocket 实时接收。

一致性保证

以服务端落库为唯一事实来源(Single Source of Truth)。客户端本地缓存仅作展示优化,冲突时以服务端数据为准。

通话与会议信令

音视频媒体流通过 WebRTC 在终端之间直连传输,服务端仅转发信令(SDP / ICE Candidate),不中转音视频数据。

  1. 主叫方通过 REST 创建通话会话,服务端向被叫方 WebSocket 推送 CALL_INVITE
  2. 被叫接听后,双方经 WebSocket 交换 SDP Offer/Answer 与 ICE Candidate。
  3. WebRTC 连接建立,音视频 P2P 传输;挂断时发送 CALL_HANGUP 释放资源。

多人 Mesh 会议沿用同一信令通道,每位参与者与其他成员建立独立 PeerConnection,适合小规模协作场景。