HTML5本身不提供心跳包机制,但可通过WebSocket协议实现可靠心跳检测;需客户端定时发ping、监听pong响应并设超时,服务端须快速回pong且禁用耗时处理,形成“发—等—收—判”闭环。

HTML5 本身不直接提供“心跳包”机制,但结合 WebSocket 协议(HTML5 标准的一部分)可实现可靠的心跳检测,防止连接因中间代理、NAT 超时或网络空闲被意外关闭。关键不在 HTML5,而在 WebSocket 客户端与服务端协同设计。
WebSocket 心跳的必要性
浏览器原生 WebSocket 连接在无数据传输时,可能被防火墙、负载均衡器(如 Nginx)、运营商 NAT 设备静默断开(常见超时为 60–300 秒)。浏览器不会主动通知断连,readyState 可能仍显示 OPEN,导致后续发送失败却无感知。心跳是唯一可主动探测连接活性的通用手段。
客户端心跳实现(JavaScript)
在 WebSocket 连接建立后,启动定时器定期发送轻量消息(如 "ping" 或空 JSON {"type":"heartbeat"}),并监听响应确认存活:
- 使用 setInterval 发送(建议 25–45 秒间隔,略短于服务端/中间件超时阈值)
- 避免依赖 onmessage 单一回调——需区分业务消息与心跳响应,推荐约定字段如 type: "pong"
- 设置超时检测:发送 ping 后启动 setTimeout,若指定时间(如 10 秒)内未收到 pong,则视为异常,主动 close 并触发重连
- 连接关闭(onclose)或报错(onerror)时,清除定时器,防止内存泄漏
服务端配合要点
服务端必须识别并快速响应心跳消息,不能将其当作普通业务消息处理或丢弃:
立即学习“前端免费学习笔记(深入)”;
- 收到 type="ping" 或特定字符串时,立即返回 {"type":"pong", "ts": Date.now()}(附时间戳便于客户端计算延迟)
- 禁用对心跳消息的鉴权、日志、存储等耗时操作,确保响应毫秒级
- 在连接管理模块中记录最后心跳时间,若超过阈值(如 90 秒)未收 ping,主动关闭连接并清理资源
- Node.js(ws 库)、Java(Spring WebSocket)、Go(gorilla/websocket)均支持自定义消息处理逻辑,无需额外长轮询
替代方案对比与避坑提醒
不推荐以下做法:
- 依赖 WebSocket 的 built-in ping/pong:浏览器 API 不暴露底层 ping 帧控制权,无法监听或定制;服务端即使自动回 pong,客户端也无法捕获确认
- 用 setTimeout 模拟心跳但不校验响应:仅发不收等于无效,无法发现单向断连(如服务端已掉线但客户端仍能发)
- 心跳间隔 > 中间设备超时:例如 Nginx 默认 proxy_read_timeout 60s,心跳设为 70 秒必然断连
- 在 onopen 中一次性启动心跳,忽略重连场景:每次新连接建立后都需重新初始化定时器
真正稳定的心跳不是单点发送,而是“发—等—收—判”的闭环。只要客户端和服务端按约定节奏交互,WebSocket 长连接可在复杂网络下持续数小时甚至数天不断开。











