WebSocket 心跳机制与断线重连
场景题: “现有的系统使用 WebSocket 进行实时的即时通讯(IM)或者大屏数据大盘的毫秒级推送。 但是在弱网(比如进电梯、换网络环境)或者服务端 Nginx 为了安全强制断掉长久无行动的连接时,系统的 WebScoket 会无声无息地‘死去’。 请问怎么用纯 JS 实现一套具有极强鲁棒性的 WebSocket 心跳检测及重型断线重连能力?”
遭遇“假死沉寂”危机
如果我们直接调用 new WebSocket(url) 且把业务写死绑定在 onmessage 上,很容易遭遇一种情况:“前端看着连接建立依然在握手着没报错,后端其实在几小时前早已经由于 TCP 等原因死掉了”,导致数据假沉寂,业务崩塌。这就是为什么必须做心跳检测。
核心实现设计机制
架构实现中,我们将封装这个类为拥有两副重型铠甲的生命体:跳动的源泉(心跳探针) 与 不屈的重生(断网重试)。
Phase 1:心跳检测 (Heartbeat)
为了避免“不知不觉地假死”,前端必须养成每隔一段时间就发一句“喂”(Ping),后方一旦活着就秒回一声“哈”(Pong)。
心跳策略机制:
- 触发定时器:利用特定的时长(例如 30 秒),只要我们长时间没有收到远端的回信我们就在倒计时完毕后发一段如
'ping'的字符串。 - 清脆的一发二响(重定时器):不仅发包,我们在这个时机开启另一颗延时定时雷(如 10 秒后爆炸),如果远端在 10s 后竟然还在沉睡没发回任何含
'pong'之类的答复,这颗雷就会爆,强行断定为连接死亡,主动触发断开重建生命周期! - 安全触网续命:若是 10s 内对方传来了任何有效信息或者特定的 'pong' 响应,我们一把抹除重定时雷的发生,且刷新心跳时钟从 0 继续等待下一次漫游侦测。
Phase 2:断线重连 (Reconnect)
无论是因为心跳停止还是外部网线遭到物理拔除断裂:系统收到 onclose 或者 onerror 后不能一味地报个 Error 让用户看报错页。它必须开启自动挽救功能。
挽救重连策略机制:
- 上锁(Lock):不能任由短时间内狂风骤雨地发起成百上千次
new WebSocket。设定isReconnecting锁并只允许进入一种连接复原重绘的序列。 - 衰退重试 (Exponential Backoff, 指数退避算法):不要像愣头青一样死死地每秒查一次。如果网络被拔了,可以采用一开始等 3 秒;随后失败等 5 秒,再失败拉长时间等 10 秒去连接的退守策略,给服务端喘息的时间避免引发 DDOS 并保护客户端 CPU。最大重复次数设限如 5 次不通过直接彻底宣布连接溃败死亡向屏幕上爆弹窗提示。
可以默写的经典伪骨架代码展示
面试要义
面对这样一道带有架构味道的工程问题,你的核心展现是展现出对边界网络危机的恐惧,不相信单纯底层 TCP。要说出如何利用 Ping/Pong 把前端的绝对主动握手权牢牢掌控住;并在描述遭遇极端脱网重连时,重点利用“不暴库的 Exponential 延缓时间递增”表现出一个沉淀极其稳重的前端防守底蕴。

