假死连接是怎么出现的
NAT、防火墙、负载均衡这类中间设备会静默清理长时间空闲的会话,而两端仍然以为连接存在,这就是假死连接。表现很有规律:空闲一段固定时间后第一次写数据,要么立刻收到 RST,要么反复重传直到超时才发现连接早已不可用。抓包里能直接把保活周期与空闲时长测出来,验证假设。
基本信息
| 观察点 | 空闲期之后首次写数据的异常与重传 |
|---|---|
| 关键时长 | 中间设备老化时间,例如 NAT 会话超时 |
| 对策 | 保活间隔小于链路上最短的老化时间 |
| 对照手段 | 应用层心跳与 TCP Keep-Alive |
典型使用场景
- 长连接应用在空闲后首次请求必现失败
- 排查「每天固定时段断连」这类有规律的现象
- 设计心跳间隔时找到取值依据
- 区分连接被设备清理与服务端进程重启
- 评估负载均衡会话保持策略对长连接的影响
观察与测量
观察与测量
tshark -r a.pcap -Y "tcp.flags.reset==1" -T fields -e frame.number -e ip.src -e tcp.srcport -e frame.time_relative
# 看 RST 出现的时间点,与上一次数据发送之间的间隔就是空闲时长
tshark -r a.pcap -Y "tcp.keep_alive" -T fields -e frame.number -e frame.time_relative | head -20
# 抓到保活包就能直接测出周期,与设备老化时间对照
tshark -r a.pcap -Y "tcp.analysis.retransmission" -T fields -e frame.number -e tcp.stream | head
# 空闲后首写触发连续重传,是会话已被清理的典型形态现象对照
| 现象 | 可能原因 | 确认方式 |
|---|---|---|
| 空闲固定时长后首写失败 | NAT 或防火墙老化 | 对比 RST 时间与空闲时长 |
| 首写触发连续重传后超时 | 会话被静默清理 | 看对端是否完全无响应 |
| 立即收到 RST | 中间设备或对端明确拒绝 | 看 RST 的源地址 |
| 保活包长期无应答 | 对端已不可达 | 检查保活周期与失败计数 |
应用层心跳通常比 TCP Keep-Alive 更可控:间隔与载荷都能自定义,还能携带业务语义,既容易被中间设备识别,也便于自身监控统计。TCP Keep-Alive 在多数系统上需要应用显式开启,默认并不生效。
不同设备的老化时间不一致,设计时取链路上最短的那个值作为输入。另外只调心跳不设重连退避,会在网络恢复瞬间形成重连风暴,把刚恢复的链路再打垮一次。
排查顺序
- 先确认失败是否总在空闲之后,找出空闲时长的量级
- 在抓包里测量实际保活周期,确认是否小于设备老化时间
- 核对链路各段设备的老化配置,取最短值作为设计依据
- 区分是设备清理还是服务端重启,看服务端日志与进程状态
- 补上重连退避策略,避免集中重连放大故障