WebSocket需手动实现心跳机制,常用客户端主动发送“ping”消息(30–45秒间隔),服务端响应“pong”;亦可利用协议原生Ping/Pong帧降低开销;应结合页面可见性节流、超时检测及指数退避重连策略保障连接可靠性。

WebSocket 本身不自动发心跳包,必须手动实现。核心思路是:在连接建立后,按固定间隔向对端发送轻量消息(如 "ping" 或 {"type":"ping"}),服务端收到后应尽快响应(如 "pong" 或 {"type":"pong"}),客户端通过是否按时收到响应来判断连接是否存活。
客户端主动发心跳(最常用)
适合多数业务场景,控制权在前端,逻辑清晰、易于调试:
- 连接成功(onopen)后立即启动定时器,推荐间隔 30–45 秒(比服务端空闲超时阈值小 10–15 秒)
- 用 setInterval 或更稳妥的 setTimeout 链式调用(避免页面后台时定时器堆积)
- 每次发包前检查 ws.readyState === WebSocket.OPEN,或用 try/catch 包裹 send() 防止报错
- 心跳内容尽量精简:纯字符串 "ping" 比 JSON 更快;若需时间戳,用 {"t":"h","ts":1727851200} 即可,不带业务字段
服务端主动 Ping + 客户端自动 Pong(标准高效)
利用 WebSocket 协议原生 Ping/Pong 帧,浏览器自动处理响应,无需解析 JSON,开销最低:
- 服务端(如 Node.js 的 ws 库)调用 ws.ping() 发送 ping 帧
- 客户端无需任何操作——浏览器收到 ping 后自动回 pong 帧
- 服务端监听 ws.on('pong', ...) 并配合超时检测(如 10 秒未收到则 ws.terminate())
- 注意:此方式要求服务端支持并启用该机制,前端无法主动触发标准 ping 帧
结合可见性与连接状态做节流
防止无效心跳浪费电量和流量:
- 监听页面可见性:document.addEventListener('visibilitychange', ...),隐藏时 clearTimeout 当前心跳定时器,恢复时重置并补发一次
- 发送心跳前确认连接状态,断连或关闭中直接跳过
- 每次发 ping 后启动独立的超时检测(如 setTimeout(..., 10000)),收到 pong 时清除并重启,避免多个 timeout 并发
- 网络异常或 send 报错时,主动 ws.close() 触发 onclose 流程,进入重连逻辑
配套重连策略不能少
心跳只是探测手段,断连后需可靠恢复:
- 在 onclose 和 onerror 中清除所有定时器,并启动重连
- 采用指数退避:首次延时 1 秒,失败后 2 秒、4 秒、8 秒……上限建议 30–60 秒
- 设置最大重连次数(如 5 次),超限后提示用户或降级为轮询
- 重连成功后重新初始化心跳,避免新旧定时器共存
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











