WebSocket无内置心跳,需应用层实现:客户端定时发{"type":"ping"},服务端立即回{"type":"pong"},超时未响应则重连。

WebSocket 默认没有内置心跳机制,长时间无数据交互时,中间代理(如 Nginx、负载均衡器)或防火墙可能主动关闭空闲连接。客户端主动发送 Ping(实际是 WebSocket 的控制帧),服务端自动回 Pong,这是协议原生支持的机制——但浏览器中 JS 无法手动发送 Ping 帧,必须靠服务端配合或应用层模拟。真正可行且通用的做法是:在应用层定时发自定义心跳消息(如 {"type":"ping"}),服务端收到后立即返回 {"type":"pong"},客户端据此判断连接是否健康。
1. 客户端定时发心跳消息(应用层 Ping)
使用 setInterval 定期发送 JSON 消息,频率建议 20–30 秒(避开多数代理默认 60 秒超时):
- 先检查
ws.readyState === WebSocket.OPEN,避免向关闭/连接中状态发消息 - 心跳消息格式统一,例如
{ "type": "ping", "ts": Date.now() },便于服务端识别和客户端校验 - 可选:记录上次发送时间,防止 setInterval 失控累积
2. 客户端监听 Pong 响应并维护心跳状态
不是靠底层 Ping-Pong 帧,而是监听服务端返回的 {"type":"pong"} 消息:
使用固定的 Next.js/Tailwind/Prisma 技术栈构建并记录独立 SaaS 项目,仅将 FastAPI 用于 Python 工作负载,并遵循严格的架构规范。
- 收到
pong后重置“未响应”计时器(如清除上一个setTimeout) - 若超过预期时间(如 5 秒)未收到 pong,视为心跳失败,可触发重连逻辑
- 建议加个简单标记,如
isHeartbeatAlive = true,供业务层快速判断连接可用性
3. 处理断线与自动重连(配合心跳)
心跳失败 ≠ 立即断开,但它是比 onclose 更早的预警信号:
- 连续 2–3 次心跳超时(非单次失败),再执行
ws.close()并启动重连 - 重连前清空旧定时器(
clearInterval/clearTimeout),避免内存泄漏 - 重连可加入退避策略,如首次 1s,失败后 2s、4s、8s… 避免雪崩
4. 服务端需明确支持该心跳协议
客户端再完善,服务端不响应也没用。关键点:
- 识别
{"type":"ping"},不处理业务逻辑,立刻回复{"type":"pong","ts":...} - 不要把 ping 当普通消息丢进业务队列,延迟响应会导致客户端误判
- 部分框架(如 Socket.IO、ws 库)提供
pingTimeout/pingInterval配置,优先使用其原生能力
浏览器里 JS 不能直接触发 WebSocket 协议级 Ping 帧,所以所谓“客户端心跳”,本质是应用层约定 + 定时消息 + 状态管理。核心不在技术多难,而在客户端和服务端严格对齐心跳格式、超时阈值和响应行为。

















