某推送服务进入低流量后,WebSocket 连接几乎每 90 秒断一次。应用 PONG 正常,客户端却超时;代理记录会话过期,上游没有 close 帧。只盯错误码,团队会在调心跳、改代理超时和密集重连间反复折腾,甚至引发重连风暴。
如果你正在选机器,或者想先把线路和配置跑通再谈长期方案,可以先看看这几家的线路说明和技术参数:synexvm(海外服务器),先看清带宽线路、流量策略和退款条款,再决定要不要迁。
排障重点不是猜 close 码,而是确认谁停止转发、TCP 是否收到 FIN/RST、close 帧来自哪里,以及 NAT 映射是否仍存在。
WebSocket 建连后,TCP 状态、代理会话和协议帧共同维持连接。应用心跳超时指窗口内未收到 PONG 或业务确认,常见于事件循环阻塞、线程池耗尽或单向黑洞;此时 TCP 仍可能显示 ESTABLISHED。

代理空闲回收由 LB 或网关的 idle timer 触发,有些策略不计控制帧,达到阈值便删会话且不转发 FIN。NAT 映射失效多无 close 帧:公网原端口消失,本地 socket 仍像存在,形成半开连接。上游断开常见于发布、限流或摘流,通常能看到上游 close 帧、FIN/RST 或清理日志。固定周期只能缩小范围,报文来源和方向才是证据。
先给连接编号,在客户端、代理、上游用同一时钟记录 Upgrade、PING/PONG、业务帧、close 码、FIN/RST 和对端地址。若使用的观测台(如 ServLlama)支持连接号聚合,便可对齐事件;时钟未同步,“同一秒断开”没有意义。

再从客户端与上游双端抓包。客户端 PING 已发出,上游既未收也未回,查中间路径或接收线程;上游收到却无 PONG,查应用阻塞;代理恰在固定阈值删会话,指向代理空闲回收;上游先发 close、FIN 或 RST,指向发布、限流或连接清理。
最后做旁路探测:样本走相同 NAT、代理和上游,每 30 秒发 Ping,要求 5 秒内收到 Pong,同时测试新 TCP 握手。旧连接沉默而新握手成功,更像映射或旧会话被回收;两者都失败,再查路由、代理和上游容量。切勿持续给故障样本发包,否则会续命 NAT、改写空闲计时,掩盖根因。
按“发出对端收到响应返回应用消费”四段打点,某段缺失就只查该段。TCP keepalive 不等于业务心跳;重连须加退避、抖动和并发上限,避免放大重连风暴。
排查时先区分主动关闭、进程退出、TCP 连接被重置和路径静默。客户端连续多个心跳周期未收到业务响应,可判定为心跳超时检测触发;连接仍在系统表中,却无法收发数据,则是典型的半开连接识别场景。抓包若看到 FIN、RST,属于明确关闭;若只看到心跳发出、没有 Pong 或业务帧回程,应沿网关和应用链路逐跳定位。
常见误区是把 TCP Keepalive 当成 WebSocket 保活,或只让客户端发送 Ping。TCP 探活只能确认部分传输层状态,Pong 也只证明对端网络栈在线,不能证明业务线程健康。服务端应记录连接 ID、最后收包时间、最后发包时间、Ping/Pong 序号及关闭原因;心跳间隔还要明显小于最靠近客户端的空闲回收阈值,并为网络抖动留出余量。
若应用日志没有关闭事件,而负载均衡器或反向代理率先断开,重点检查代理空闲回收:对比客户端、Ingress、Nginx、负载均衡各层的 idle timeout、连接上限和请求头超时。心跳虽然能刷新部分连接的活跃状态,但代理是否识别 WebSocket 帧、是否清理 Upgrade 后的旁路连接,必须通过持续抓包和超时测试确认。

跨运营商或企业防火墙时,还要排查NAT 映射失效。状态表老化、地址转换变化、双向路由不一致,都可能让长连接看似建立却无法继续传输;通过固定四元组抓包、切换出口和缩短观察时间,可区分 NAT 问题与业务阻塞。服务端恢复后,大量客户端同时重连会形成重连风暴治理压力,应使用指数退避加随机抖动、设置重试上限与总预算,并在入口限制并发握手,优先恢复关键会话。
可执行检查清单:①统一时钟并关联客户端、代理、服务端日志,确认第一个缺失的心跳或数据帧;②抓取握手后十分钟的流量,核对 FIN、RST、序列号及重传情况;③列出每层空闲超时,按“心跳间隔<最短回收阈值”调整并验证;④模拟拔网、进程退出、链路限速和代理重启,分别验证半开识别与关闭原因;⑤在 NAT 或 CGNAT 环境执行长连接与双向流量测试;⑥上线退避抖动、并发握手上限和连接恢复指标,告警阈值按重连速率及失败比例设置,而不是只看在线连接数。