websocket仅保证单连接内帧有序,全局顺序需客户端与服务端协同设计:客户端用client_seq标记、服务端用server_seq权威排序;重连先同步离线消息再补发;前后端均需幂等、状态机与滑动窗口保障确定性收敛。

WebSocket 协议本身不保证跨连接、跨重连或服务端多实例场景下的全局消息顺序,但能保证单个连接内帧的严格有序。真正的“消息顺序一致性”难点不在传输层,而在应用层如何定义、传递、校验和收敛这个顺序——必须靠客户端与服务端协同设计,不能依赖浏览器自动行为。
用唯一且可比的序列号锚定逻辑时序
时间戳不可靠,客户端本地递增序号(client_seq)仅作临时标记;服务端落库后生成的权威序列号(如 server_seq 或数据库自增 ID)才是排序唯一依据。
- 客户端发每条业务消息前,生成单调递增的
client_seq(如从 localStorage 读取并 +1 后存回),随 payload 一同发送 - 服务端收到后立即返回含该
client_seq的 ACK,并在撮合/处理完成后,推送带相同client_seq和最终server_seq的结果 - 客户端按
server_seq归并所有消息流(包括离线补推、重连拉取、主动请求响应),构建有序队列
重连后必须先同步再补发,避免新旧消息倒置
重连成功不等于状态一致。若直接重发未确认消息,可能让“旧请求的结果”晚于“新请求的结果”到达,造成 UI 错乱或状态跳跃。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 重连后第一件事:发送
{"type":"fetch_offline","last_server_seq":12345},向服务端索取last_server_seq之后的所有消息 - 服务端按
server_seq升序返回离线消息列表,客户端逐条写入本地有序缓冲区 - 等离线消息全部处理完毕,再从本地待确认队列中取出未 ACK 的消息,按原始
client_seq顺序重发
前端需维护轻量状态窗口,实现确定性收敛
不依赖“收到即生效”,而是通过序号状态机明确每个操作所处阶段,屏蔽中间不确定性。
- 维护滑动窗口(如大小 1024),记录每个
client_seq的当前态:pending→acked→confirmed→timeout - 只对
confirmed状态触发最终 UI 更新;对重复到达的order_report,检查是否已 confirmed,是则丢弃 - 提供
getOrderStatus(client_seq)接口,返回当前确定态,不暴露processing这类不可靠中间态
服务端必须支持幂等写入与快速 ACK
没有服务端配合,前端再严谨的序号逻辑也形同虚设。关键不是“能不能排”,而是“有没有能力拒绝乱序写入”。
- 所有业务写入前,先用
messageId(推荐crypto.randomUUID())查 Redis 缓存,已存在则跳过执行,只发 ACK - 收到任意消息,立刻返回结构化 ACK(毫秒级),不等 DB 持久化完成;ACK 中必须包含客户端可识别的序号映射
- 用户离线期间,将消息按
server_seq存入带 TTL 的有序缓存(如 Redis Stream 或 Sorted Set),供重连时分页拉取
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










