idle connection timeout:空闲连接超时的机制与对策
idle connection timeout严重程度 Low连接因为长时间没有数据往来,被链路上某一方按空闲超时关闭。这是网络世界的正常代谢而非故障;需要处理的只是当超时短于你的业务静默间隔时,用心跳压住或用重连兜底。
结论
先定性:空闲超时不是 bug,是设计。互联网上的每一台中间设备都在为有限的连接表空间精打细算,清理长期沉默的连接是它们的本职工作。这条"错误"真正的问题形态只有一种:链路上最短的那个超时,比你的应用两次说话的间隔更短——于是每次静默后再开口,发现线已经断了。对策也只有两类:让连接看起来不空闲(心跳),或者接受断开并优雅重连。
适用环境
- 全部平台
- 间歇通信的应用:IM、推送、控制通道、数据库连接池
一分钟快速判断
- 确认"空闲"前提:断开是否总发生在一段无操作之后?活跃使用中掉线不是本条,转 WS-003 或 LONG-002;
- 测阈值:用不同的保持时长各测一次(如 60 秒、120 秒、300 秒),找到"能活过"与"活不过"的分界——那就是链路的实际空闲阈值;
- 对比网络:同样的测量换个网络再做,阈值明显不同说明限制来自网络侧(NAT)而非服务端。
这条错误代表什么
一条空闲连接要活下来,需要沿途所有计时器都不到期。数一数这些计时器:家用路由器的 NAT 表(典型几分钟)、运营商级 NAT(蜂窝网络上可能只有几十秒)、企业防火墙会话表、负载均衡器的 idle timeout、反向代理的 read timeout、服务端应用自己的空闲回收。最短的那个说了算。这也解释了为什么同一应用在不同网络上表现迥异——变的不是应用,是链路上最短计时器的归属。
被清表后的连接是"僵尸":两端都以为连接还在,直到一方发数据才触发真相(RST 或超时)。所以空闲超时的报错时机总在"恢复活动的那一刻",而不是超时发生的时刻——排查时把时间线倒回最后一次成功通信,间隔才是关键数字。
ConnProof 如何判断
connproof websocket wss://你的服务地址/path --hold 300000ConnProof 的保持检测期间会发送 ping 维持活性,因此它测出的是"有心跳时能活多久";要测纯空闲阈值,观察你的应用在不同静默间隔后的存活状态并记录分界值。两组数据(有心跳 / 纯空闲)对照,就能算出心跳需要多密。
最常见原因
- NAT 表超时:家宽几分钟、蜂窝几十秒到一两分钟;
- 服务端/网关 idle timeout:Nginx 默认 60 秒是著名的"一分钟掉线"来源;
- 移动系统省电:后台应用的连接被系统主动挂起回收;
- 心跳间隔配置大于链路阈值:有心跳等于没心跳。
桌面端排查步骤
- 按上文测出实际阈值;
- 把应用心跳设为阈值的三分之一到一半;
- 自家服务则直接调服务端参数:把代理/网关的空闲超时调到大于业务最长静默期;
- 无法加心跳的场景(第三方应用无此设置),确认其自动重连可用,把关注点从"不断"转移到"断了无感"。
手机端排查步骤
- 手机后台的空闲断开由系统电源管理主导,心跳打不过系统——正确姿势是依赖推送通道(系统级长连接)+ 回前台快速重连;
- 需要长期在线的特殊应用(监控、对讲类)按厂商文档申请后台白名单;
- 蜂窝网络阈值天然短,无解也无需解,重连兜底即可。
如何区分本地问题和节点问题
| 证据 | 结论 |
|---|---|
| 换网络后阈值变化 | 网络侧 NAT(本地环境属性) |
| 任何网络阈值一致 | 服务端/网关配置 |
| 只在手机后台发生 | 移动系统省电策略 |
| 心跳加密后仍按时断 | 不是空闲超时,转存活上限类问题 |
TCP keepalive 与应用层心跳的区别
容易混淆的一点:操作系统提供的 TCP keepalive 与应用层心跳不是一回事,效果也不同。TCP keepalive 由内核发送空探测包,默认间隔极长(多数系统两小时),且部分 NAT 设备不把它计入"活跃"——指望系统默认的 keepalive 保活基本会落空。应用层心跳(WebSocket 的 ping/pong、协议自带的 heartbeat 帧)由应用主动发真实数据,间隔可控、被链路普遍认可,是对抗空闲超时的正规武器。排查时的对应关系:应用有心跳设置就调应用的;应用没有暴露设置而你怀疑空闲超时,先用 ConnProof 的保持检测(自带 ping)验证"有心跳能活"——能活就去给应用找心跳配置或提需求,而不是去调系统的 keepalive 参数,后者动了也大概率无效。
仍未解决时收集什么信息
- ConnProof 错误码(LONG-003)与脱敏报告;
- 测得的空闲阈值与测量方法;
- 有无心跳两种条件下的对照;
- 网络环境(家宽/蜂窝/公司)与设备平台。
禁止提交:完整订阅链接、密码、验证码、私钥、Token。
重新运行检测
connproof websocket wss://你的服务地址/path --hold 300000 --format markdown --output idle-report.md心跳调整到位后,连接应能跨越原阈值持续保持。验证时把保持时长设为原阈值的三倍以上,跑满仍存活才算数——只比阈值多一点的通过可能只是计时器抖动的侥幸。
相关文档
更新记录
- 2026-07-28:规则 v1 发布,确立阈值二分测量法。