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,则视为连接失效:
jslet 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同时触发造成冲突,可错开间隔或由一方主导。
重连策略怎么设计?
断开后应采用指数退避重连,避免大量客户端同时重连导致服务器雪崩:
jslet 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(); };
还有哪些最佳实践?
- 动态调整间隔:网络良好时拉长间隔节省资源,弱网下缩短间隔加快检测
- 状态监控:记录心跳延迟和丢包率,用于运维告警和间隔调优
- 重连成功后重置退避计数,避免下次断开仍从高延迟开始