WebSocket 推送进度需后端主动驱动,核心是通过唯一任务 ID 绑定用户与连接,定时轮询状态并定向推送,结合 Redis 持久化进度、映射表管理会话、生命周期清理及前端重连机制保障精准、安全、及时。

WebSocket 本身不主动推送进度,后端必须自己驱动推送逻辑。核心不是“怎么连 WebSocket”,而是“怎么让进度变化精准、安全、及时地抵达对应前端”。
用唯一任务 ID 绑定连接
用户发起任务(如上传、视频生成)时,前端需生成并传递一个全局唯一 ID(如 taskId 或 uploadId),常见方式包括:
- HTTP 接口提交任务时,作为请求参数或响应体返回该 ID
- WebSocket 连接建立后,前端立即发送一条绑定消息:
{"action":"bind","taskId":"t_8a9f2b"} - 后端收到后,将该 ID 与当前 WebSocketSession 存入线程安全结构(如 Java 的 ConcurrentHashMap
)
避免用时间戳、随机数等易重复的方式生成 ID;多个任务共用同一 ID 会导致消息错发或覆盖。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
定时查进度 + 定向推消息
后端启动任务后,不能依赖 WebSocket 连接自身触发更新,而应另起定时机制轮询或监听任务状态:
- Spring 生态推荐使用 TaskScheduler,配合 @Scheduled 或 scheduleAtFixedRate
- Node.js 可用 setInterval,但务必在连接关闭时 clearInterval,防止内存泄漏
- 每次执行时,根据 taskId 查询当前进度(从 DB、Redis 或内存缓存中读取)
- 查到进度后,从映射表中取出对应 session,先校验 session.isOpen()(Java)或 ws.readyState === WebSocket.OPEN(Node),再调用 session.sendMessage() 推送 JSON 消息
状态持久化与多实例兼容
进度数据不能只存在单机内存里,否则重启或集群部署会丢失状态:
- 把任务进度写入 Redis(如
SET task:t_8a9f2b "{\"percent\":65,\"msg\":\"渲染第3帧\"}",带过期时间) - 定时任务从 Redis 读取,而非本地变量,确保多节点都能访问一致状态
- 任务完成或失败后,主动清理 Redis 中的进度键,并从 session 映射表中移除该 taskId
连接生命周期管理
WebSocket 是长连接,但会因网络波动、页面关闭、超时自动断开:
- 在 @OnClose(Java)或 ws.on('close')(Node)中,遍历映射表,删除所有指向该 session 的 taskId 条目
- 前端应实现自动重连(带退避策略),重连后重新发送 bind 消息,避免断线后进度停止更新
- 可加简单心跳机制(如服务端每 30 秒发 ping,客户端回 pong),识别并清理僵死连接

















