展现层
linkx-client(Electron + Vue 3)与 linkx-admin(Vue 3 管理后台)负责用户交互与界面渲染。
深入 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,减少轮询开销。客户端登录成功后两条通道同时可用。
用户发送一条聊天消息时,链路如下:
POST /api/message/send。用户输入 → 客户端 REST 发送 → 服务端鉴权 & 落库
↓
Netty 推送给在线接收方
↓
接收方 WebSocket 收到 → UI 渲染新消息
客户端登录后自动建立 WebSocket 长连接,并在 Header 或首帧携带 JWT 完成鉴权绑定。
ws://host:8081/ws → 服务端将 Channel 与用户 ID 绑定。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),不中转音视频数据。
CALL_INVITE。CALL_HANGUP 释放资源。多人 Mesh 会议沿用同一信令通道,每位参与者与其他成员建立独立 PeerConnection,适合小规模协作场景。