排查长连接断开需提前捕获心跳超时、rst重置、ack丢失或中间设备静默切断等异常信号;用tcpdump锁定五元组抓包,关注flags [r]、空闲期后无ack的发包、keepalive探测有去无回及time_wait端口耗尽等问题。

排查长连接断开,关键不是等它“突然消失”,而是提前捕获连接维持过程中的异常信号——比如心跳超时、RST重置、ACK丢失或中间设备静默切断。tcpdump 能帮你看到连接在哪个环节“失联”,比应用日志更底层、更真实。
抓取指定连接的持续流量,带时间戳和序号
先锁定问题连接的五元组(源IP/端口、目的IP/端口),再针对性抓包:
-
基础命令:
sudo tcpdump -i eth0 -nn -S -tt -w conn.pcap 'host A.A.A.A and host B.B.B.B and port 8080' -
-S显示绝对 TCP 序号,方便判断重传或乱序;-tt输出精确到微秒的时间戳,利于分析超时行为;-w保存为 pcap 文件,后续可用 Wireshark 深度分析 - 若不确定端口,可先用
ss -tinp | grep ESTAB查出活跃长连接的 PID 和端口
重点观察连接空闲期是否被单向切断
长连接常因中间设备(如云LB、防火墙)设置较短空闲超时而被“悄悄”断开,本端无感知,直到下一次发包才收到 RST 或超时:
- 在抓包结果中搜索
Flags [R]—— 表示对端主动发送 RST 终止连接 - 查找长时间(如 >60 秒)无数据交互后,突然出现的
SYN或[P.]/[.].包未被 ACK 回应 —— 可能是连接已失效但本端仍尝试通信 - 对比
tcp_keepalive_time(默认 7200 秒)与 LB 的空闲超时值(常见 60–180 秒),若后者更短,就极易触发单向断连
结合 keepalive 探针确认内核行为
Linux 内核会按 tcp_keepalive_* 参数自动发送探测包,tcpdump 可验证它们是否发出及是否有回应:
- 运行
sysctl net.ipv4.tcp_keepalive_time net.ipv4.tcp_keepalive_intvl net.ipv4.tcp_keepalive_probes查当前值 - 在抓包中过滤 keepalive 包:
tcpdump -nn -i eth0 'tcp[tcpflags] & (tcp-syn|tcp-fin|tcp-rst) == 0 and tcp len == 0'(空载荷 ACK 包,通常是 keepalive 探测) - 若看到多个连续 keepalive 包发出但无响应,且最终出现 RST 或连接卡在 FIN_WAIT1,说明对端已下线或中间链路中断
排除端口复用与 TIME_WAIT 干扰
长连接意外断开后,若客户端快速重连,可能撞上本端残留的 TIME_WAIT 或端口耗尽问题,表现为 connect() 失败而非连接建立后断开:
- 抓包时留意客户端 SYN 是否根本没发出去,或发出后无 SYN+ACK 回应 —— 这往往不是连接断开,而是连接压根没建起来
- 配合
ss -s查看TIME-WAIT数量,若接近 65535 且net.ipv4.tcp_tw_reuse = 0,新连接会被内核拒绝 - 此时 tcpdump 中看不到任何目标 IP 的包,
ss -tnop却显示大量TIME-WAIT,就是端口资源瓶颈











