长连接空闲断链
长连接空闲一段时间后会被中间设备按会话老化时间回收:NAT、防火墙、负载均衡各自维护会话表,超时即静默删除,连接两端并不知情。下次再往这条连接上发数据时,表现就是「发了没反应」或直接收到 RST。排查的核心工作是把实际空闲时长与设备老化时间对上。
基本信息
| 适用平台 | 所有经过 NAT、防火墙或负载均衡的 TCP 长连接 |
|---|---|
| 老化时间量级 | 从数十秒到数小时不等,取决于设备与配置 |
| 典型症状 | 空闲后首次请求无响应,超时重连后才恢复 |
| 标准参考 | RFC 5382(NAT 行为) |
典型使用场景
- 排障切入:先记录首次失败之前连接空闲了多久
- 参数对齐:把应用心跳间隔设得比设备老化时间更短
- 复现验证:空闲指定时长后再发一次请求并同时抓包
- 区分责任:判断是服务端主动关闭还是中间设备静默回收
- 长轮询设计:评估心跳与重连策略,避免恢复瞬间齐刷
排查步骤
排查步骤
# 1) 记录失败前最后一次正常通信的时间点
# 2) 对比链路设备的会话老化时间配置
# 3) 让应用心跳间隔小于老化时间
# 4) 空闲 N 分钟后复现,抓包观察两段流量之间的空白区间
ss -tn state established '( dport = :8443 )' # 确认连接在本机是否还在断链特征对照
| 特征 | 服务端主动关闭 | 中间设备静默回收 |
|---|---|---|
| 是否可见 FIN | 能看到 FIN 或 RST | 两端都看不到 |
| 失败时表现 | 发数据立刻收到 RST | 发了没反应,最终超时 |
| 复现条件 | 与空闲时长无关 | 与空闲时长强相关 |
| 修复方向 | 调整服务端保持策略 | 缩短心跳间隔 |
只有应用层自己发心跳才可靠。内核的 Keep-Alive 默认间隔通常是两小时,远大于多数 NAT 设备的老化时间,指望它来保活往往起不到作用。
负载均衡的入向与出向会话表不一致时,断链会表现为单向可用:一侧能发、另一侧收不到。这种场景应以负载均衡的会话表为准,而不是只看两端主机。
抓包里最直接的证据是失败前最后一条报文与恢复后第一条报文之间的空白区间。把这段时长与设备老化时间对照,就能判断是否属于静默回收。