6月1日 02:15

WebSocket 心跳机制怎么实现?ping/pong 超时重连方案

WebSocket心跳机制通过定时发送ping/pong帧来维持连接活跃。客户端每隔固定间隔向服务器发送ping,服务器收到后返回pong,若客户端在超时时间内未收到pong则判定连接断开并触发重连。心跳的核心作用有三个:一是检测连接是否存活,TCP连接半打开时应用层无法感知;二是防止NAT超时或防火墙因空闲连接而切断链路;三是实现快速故障恢复,避免等到下次数据发送时才发现连接已断。WebSocket协议本身定义了ping/pong控制帧,但实际开发中也常用自定义文本消息(如{"type":"ping"})实现,灵活性更高且便于扩展业务数据。

追问

心跳间隔怎么定?

推荐30-60秒。间隔过短增加服务器负担和带宽消耗,间隔过长又无法及时检测断开。具体值需权衡:移动网络下NAT超时通常2-5分钟,心跳间隔应小于NAT超时的一半。对实时性要求高的场景可缩短到15-25秒。

超时处理怎么做?

发送ping后启动超时定时器,若在阈值内(通常为心跳间隔的2-3倍)未收到pong,则视为连接失效:

js
let heartbeatTimer, timeoutTimer; function startHeartbeat() { heartbeatTimer = setInterval(() => { ws.send('ping'); timeoutTimer = setTimeout(() => { ws.close(); // 超时未收到pong,关闭连接 }, heartbeatInterval * 3); }, heartbeatInterval); } ws.onmessage = (e) => { if (e.data === 'pong') { clearTimeout(timeoutTimer); // 收到pong,清除超时 } };

双向心跳是什么?

只由客户端发起心跳时,如果客户端崩溃,服务器无从得知。双向心跳让服务器也定时发ping,双方互检连接状态,避免单侧故障盲区。实现时注意避免双方ping同时触发造成冲突,可错开间隔或由一方主导。

重连策略怎么设计?

断开后应采用指数退避重连,避免大量客户端同时重连导致服务器雪崩:

js
let retryCount = 0; const maxRetry = 5; function reconnect() { const delay = Math.min(1000 * Math.pow(2, retryCount), 30000); setTimeout(() => { retryCount++; connect(); }, delay); } ws.onclose = () => { if (retryCount < maxRetry) reconnect(); };

还有哪些最佳实践?

  • 动态调整间隔:网络良好时拉长间隔节省资源,弱网下缩短间隔加快检测
  • 状态监控:记录心跳延迟和丢包率,用于运维告警和间隔调优
  • 重连成功后重置退避计数,避免下次断开仍从高延迟开始
标签:WebSocket