WebSocket心跳与断线重连

背景

WebSocket 连接看起来是“长连接”,但在真实网络环境里会被 NAT、网关、负载均衡、移动网络切换等因素中断。没有心跳和重连,页面会表现为“看似在线,实际上数据已断流”。

目标

构建一套可落地策略:

  • 快速发现连接失活
  • 避免重连风暴
  • 在网络抖动时保证用户体验

心跳设计

服务端与客户端职责

  • 客户端:定时发送 ping(或业务心跳包)
  • 服务端:及时返回 pong
  • 客户端:维护“最后一次收到消息时间”

推荐参数

  • 心跳间隔:20~30 秒
  • 超时阈值:2~3 个心跳周期
  • 断线判定:超过阈值未收到任何消息(不仅仅是 pong)

如果业务本身消息很频繁,可降低心跳频率,避免无效流量。

重连策略

指数退避 + 抖动

不要固定 1 秒重连。建议:

  • 第 1 次:1 秒
  • 第 2 次:2 秒
  • 第 3 次:4 秒
  • 上限:30 秒
  • 加随机抖动:delay * (0.8 ~ 1.2)

这样可以避免服务恢复时大量客户端同时打满连接入口。

何时停止重连

  • 用户主动退出登录
  • 页面明确进入只读离线模式
  • 服务端返回不可恢复错误(鉴权失败等)

会话恢复

重连成功后不要只看“连接成功”,还要补齐状态:

  1. 重新鉴权(token 可能已过期)。
  2. 重新订阅频道/房间。
  3. 通过消息序号补拉断线期间数据。

如果没有消息序号,至少记录“最近一次时间戳”进行增量拉取。

监控指标

要把 WebSocket 当作一条生产链路监控:

  • 在线连接数
  • 每分钟断开数
  • 重连成功率
  • 平均重连耗时
  • 心跳超时占比

当“断开数升高 + 重连成功率下降”同时出现时,通常是服务端或网络侧故障。

常见坑

  • 只实现 onclose 重连,没处理“连接假活”
  • 心跳包仅前端发,服务端不回
  • 重连后忘记重新订阅,导致“连上了但没数据”
  • 多标签页重复建连,造成资源浪费

总结

WebSocket 稳定性靠的是机制而不是运气。心跳负责“快速发现问题”,重连负责“平滑恢复”,会话恢复负责“业务一致性”。三者缺一不可。

results matching ""

    No results matching ""

    results matching ""

      No results matching ""