分布式直播 WebSocket 架构说明
1. 方案目标
直播 WebSocket 服务在多节点部署场景下,需要具备以下能力:
- 多节点广播消息一致投递
- 跨节点重复登录踢线
- 全局在线状态统一统计
- 房间状态跨节点同步
- 房间下线后所有节点统一清理连接
- 商品讲解状态跨节点一致
直播 WebSocket 采用如下方案:
本地 Session + Redis 在线态 + Redis 状态中心 + Redis Pub/Sub 事件总线
2. 设计原则
- WebSocket
Session只保存在本机内存,不能跨 JVM 共享 - 所有跨节点共享状态统一存放到 Redis
- 所有跨节点控制动作统一通过 Redis Pub/Sub 分发
- 本地 Map、队列、短缓存只作为本节点投递与性能优化层,不作为唯一状态源
- 节点间不直接互调 WebSocket 内存结构,统一通过 Redis 解耦
3. 总体架构
3.1 三层结构
分布式直播 WebSocket 架构分为三层:
-
本地连接层
每个节点仅维护自己持有的真实 WebSocketSession,例如用户连接 Map、主播连接 Map、房间消息队列、主播消息队列等。 -
分布式状态层
Redis 作为跨节点共享状态中心,统一保存:- 用户在线连接元数据
- 主播在线连接元数据
- 房间在线用户集合
- 房间在线主播集合
- 全局用户连接集合
- 全局主播连接集合
- 房间状态
- 商品讲解状态
-
分布式事件层
Redis Pub/Sub 作为跨节点事件总线,负责广播、踢线、房间清理等事件的跨节点分发。
3.2 方案定位
该方案属于共享状态 + 事件总线模式,适用于多节点部署的实时通信场景。
方案边界如下:
- WebSocket 长连接落在具体节点上
- 节点之间不共享
Session对象 - 统一通过 Redis 共享状态、传递控制事件
4. 核心组件
com.joolun.cloud.live.admin.config.LiveWsRedisConfigcom.joolun.cloud.live.admin.distribute.LiveWsConstantscom.joolun.cloud.live.admin.distribute.LiveWsConnectionInfocom.joolun.cloud.live.admin.distribute.LiveWsEventcom.joolun.cloud.live.admin.distribute.LiveWsEventTypecom.joolun.cloud.live.admin.distribute.LiveWsEventPublishercom.joolun.cloud.live.admin.distribute.LiveWsEventSubscribercom.joolun.cloud.live.admin.distribute.LiveWsNodeServicecom.joolun.cloud.live.admin.distribute.LiveWsPresenceServicecom.joolun.cloud.live.admin.distribute.LiveWsStateServicecom.joolun.cloud.live.admin.socket.LiveUserWebSocketServercom.joolun.cloud.live.admin.socket.LiveAnchorWebSocketServercom.joolun.cloud.live.admin.controller.LiveRoomController
5. Redis 数据模型
5.1 在线连接 Key
- 用户连接:
live:ws:user:{tenantId}:{roomId}:{userId} - 主播连接:
live:ws:anchor:{tenantId}:{roomId}:{userId}
连接元数据主要字段:
nodeIdsessionIdtenantIdroomIduserIdupdatedAt
5.2 在线集合 Key
- 房间用户集合:
live:ws:room:users:{tenantId}:{roomId} - 房间主播集合:
live:ws:room:anchors:{tenantId}:{roomId} - 全局用户集合:
live:ws:users - 全局主播集合:
live:ws:anchors
5.3 业务状态 Key
- 商品讲解状态:
live:ws:product:explain:{tenantId}:{roomId}:{spuId} - 房间状态:
live:ws:room:status:{tenantId}:{roomId}
6. 事件模型
6.1 Pub/Sub 通道
- 统一通道:
live:ws:event
6.2 事件类型
USER_BROADCASTANCHOR_BROADCASTUSER_COUNT_CHANGEDKICK_USERKICK_ANCHORCLEANUP_USERSCLEANUP_ANCHORS
6.3 事件职责
USER_BROADCAST:将房间消息投递到所有节点的本地用户连接ANCHOR_BROADCAST:将主播相关消息投递到所有节点的本地主播连接USER_COUNT_CHANGED:同步房间在线人数变化KICK_USER/KICK_ANCHOR:按nodeId + sessionId精准关闭旧连接CLEANUP_USERS/CLEANUP_ANCHORS:通知所有节点清理指定房间本地连接
7. 关键流程
7.1 用户连接建立
- 校验全局连接限制
基于 Redis 全局用户集合统计。 - 校验房间有效性
- 处理重复登录
查询 Redis 历史连接;如旧连接位于其他节点,则发布踢线事件。 - 注册本地
Session - 注册 Redis 在线态
包括连接 Hash、房间集合、全局集合。 - 推送连接成功消息和在线人数变更消息
7.2 主播连接建立
- 校验全局主播连接限制
- 校验直播间与主播权限
- 处理主播重复登录
- 注册本地
Session与 Redis 在线态 - 同步房间状态到 Redis
- 满足开播条件时,更新房间状态为
LIVING
7.3 心跳与失效清理
- 本地心跳任务定期扫描本节点连接
- 活跃连接刷新 Redis 连接信息时间戳或 TTL
- 失效连接同时清理本地内存与 Redis 在线态
7.4 房间下线
管理端执行 /liveroom/offline 后,依次处理:
- 广播房间下线状态
- 发布
CLEANUP_USERS - 发布
CLEANUP_ANCHORS - 更新数据库直播间状态
7.5 商品讲解状态同步
- 商品讲解状态写库后同步写入 Redis
- 各节点处理讲解消息时优先读取 Redis 状态
- 本地
PROD_EXPLAIN_CACHE仅保留为短期性能缓存
7.6 房间状态同步
- 主播连接、开播、停播、结束时同步更新 Redis 房间状态
- 房间有效性优先基于 Redis 状态判断
- 本地
ROOM_STATUS_CACHE仅作为降级缓存
8. 节点本地结构说明
以下本地结构仍然保留,用于节点内连接管理、消息投递和性能优化:
LIVE_USER_MAPLIVE_ANCHOR_MAPROOM_MESSAGE_QUEUEANCHOR_MSG_QUEUEROOM_SESSION_CACHEROOM_STATUS_CACHEPROD_EXPLAIN_CACHE
保留原因:
- WebSocket
Session必须由当前节点持有 - 本地批量投递可以降低频繁跨线程发送的成本
- 短缓存可以减少 Redis 与数据库压力
9. 适用边界
该方案适用于:
- 多节点直播服务部署
- 房间消息广播
- 用户与主播跨节点连接管理
- 在线状态统一统计
- 房间状态与商品讲解状态一致性控制
如需继续扩展到更大规模实时场景,可进一步引入专用实时网关或独立消息总线。