4、重传定位工具:tcpdump抓包分析、Wireshark重传过滤、ss/ netstat状态查看

做网络性能优化,说白了就是跟数据包打交道。重传问题尤其如此——你看不到包,就猜不到原因。我见过不少同事,一遇到超时就怀疑代码,折腾半天才发现是网卡丢包。所以这一章,咱们把三个最趁手的工具讲透:tcpdump 抓原始包、Wireshark 做可视化过滤、ss/netstat 看连接状态。三件套用熟了,重传定位基本不慌。

核心思路:先看连接状态(ss/netstat)缩小范围,再抓包确认(tcpdump),最后用 Wireshark 精确定位重传类型和触发原因。三步走,效率最高。

4.1 tcpdump:命令行抓包基本功

tcpdump 是 Linux 下最经典的抓包工具。我个人习惯在生产环境首选它——轻量、无 GUI、脚本友好。你想想看,线上服务器哪来的 Wireshark?

4.1.1 常用抓包参数

参数 作用 我常用的场景
-i eth0 指定网卡 多网卡服务器必须指定
-s 0 抓完整包(默认截断) 分析重传 payload 时必加
-w file.pcap 保存为 pcap 文件 给 Wireshark 离线分析
-c 1000 抓 1000 个包后停止 避免磁盘写爆
port 443 过滤端口 只看 HTTPS 流量
host 10.0.0.1 过滤 IP 定位特定客户端

4.1.2 重传场景抓包实战

假设你怀疑客户端到 10.0.0.1:8080 有重传。我会这样抓:

# 抓完整包,保存到文件
tcpdump -i eth0 -s 0 -w retrans.pcap host 10.0.0.1 and port 8080

# 或者直接看实时输出(适合快速验证)
tcpdump -i eth0 -s 0 -nn host 10.0.0.1 and port 8080

抓完以后,怎么快速判断有没有重传?看 TCP 序列号。同一个序列号出现两次以上,基本就是重传。我习惯用这个命令实时过滤:

tcpdump -i eth0 -nn 'tcp[tcpflags] & (tcp-syn|tcp-fin) == 0' \
  | awk '{print $3, $5, $12}' \
  | sort | uniq -c | sort -rn | head -20

嗯,这里要注意:tcp[tcpflags] & (tcp-syn|tcp-fin) == 0 是过滤掉握手和挥手包,只看数据段。然后按源IP+端口+序列号去重计数——出现次数大于1的,就是重传。

我的小技巧:生产环境抓包,一定先估算流量。比如 1000 pps 的接口,-c 10000 大概抓 10 秒。我一般先抓 3 秒看看,确认抓到目标流量再加大包数。曾经有一次没设 -c,半小时后磁盘满了……

4.2 Wireshark:重传过滤与可视化分析

tcpdump 抓到 pcap 文件后,我习惯丢到 Wireshark 里做精细分析。Wireshark 的强项是自动识别重传——它内置了重传检测逻辑,比人眼扫序列号快得多。

4.2.1 重传相关过滤表达式

过滤表达式 含义 说明
tcp.analysis.retransmission TCP 重传包 Wireshark 根据序列号和 ACK 判断
tcp.analysis.fast_retransmission 快速重传 收到 3 个重复 ACK 触发
tcp.analysis.duplicate_ack 重复 ACK 接收端催促重传的信号
tcp.analysis.lost_segment 疑似丢包 序列号不连续
tcp.analysis.ack_lost_segment ACK 丢失 发送端没收到 ACK
tcp.analysis.retransmission || tcp.analysis.fast_retransmission 所有重传 我常用的组合过滤

4.2.2 如何区分超时重传和快速重传

这是面试常问的点,也是实际排查的关键。我直接说结论:

  • 快速重传:Wireshark 标记为 TCP Fast Retransmission。特征是在收到 3 个重复 ACK 后立即重发,RTT 很短。说明网络有轻微乱序或丢包,但没超时。
  • 超时重传:标记为 TCP Retransmission。特征是重传间隔明显大于正常 RTT(通常是 RTO 级别)。说明网络可能断连或严重拥塞。

我在项目中遇到过一种情况:客户端频繁触发快速重传,但服务器端 RTT 只有 2ms。后来发现是中间交换机开启了流量整形,偶尔丢一个包。快速重传能恢复,但吞吐量掉了 30%。

避坑指南:Wireshark 的重传标记不是 100% 准确。如果抓包点不在发送端,比如在中间交换机上抓,Wireshark 可能把乱序包误判为重传。我曾经因为这个排查了三天……后来在发送端重新抓包才确认。

4.2.3 用 Wireshark 的 IO Graph 看重传趋势

除了过滤单个包,我习惯用 Statistics → IO Graph 看整体趋势。设置两个 Y 轴:

  • 一个显示总包数(蓝色)
  • 一个显示重传包数(红色)

如果红色曲线突然飙升,说明那段时间网络出了问题。配合时间轴,能快速定位到秒级的问题窗口。

4.3 ss / netstat:连接状态快速诊断

抓包之前,我一般先用 ss 或 netstat 看一眼连接状态。这两个命令能告诉你:当前有多少连接?哪些在重传?哪些已经异常?

4.3.1 ss vs netstat:我选 ss

netstat 是传统工具,但 ss 更快、信息更全。ss 直接从内核的 sock_diag 接口读数据,而 netstat 要解析 /proc 文件系统。高并发服务器上,ss 比 netstat 快一个数量级。

命令 查看重传相关指标 我的用法
ss -i 显示每个连接的 TCP 信息(含重传计数) 快速看哪些连接有重传
ss -t -i 只看 TCP 连接 过滤掉 UDP
ss -t -i state established 只看已建立的连接 排除 TIME_WAIT 干扰
netstat -s TCP 协议栈统计 看全局重传率
netstat -st TCP 统计(更详细) 对比重传段和丢包数

4.3.2 用 ss -i 定位重传连接

执行 ss -t -i,你会看到类似这样的输出:

State   Recv-Q  Send-Q  Local Address:Port   Peer Address:Port
ESTAB   0       0       10.0.0.1:8080        10.0.0.2:54321
         skmem:(r0,rb131072,t0,tb87040,f0,w0,o0,bl0,d0)
         ts sack bbr wscale:7,7 rto:204 rtt:12.5/7.5 ato:40 mss:1460
         cwnd:10 ssthresh:7 bytes_acked:1024000 bytes_received:5000
         segs_out:1200 segs_in:800 data_segs_out:1100 data_segs_in:700
         send 10.2Mbps lastsnd:2 lastrcv:4 lastack:2
         pacing_rate 20.4Mbps delivery_rate 10.1Mbps
         retrans:0/5  # ← 关键!重传次数/重传段数
         busy:0ms unacked:1 rcv_rtt:12.5 rcv_space:28960
         minrtt:8.5

看 retrans:0/5 这一项。斜杠前是重传次数,斜杠后是重传的段数。如果这个值持续增长,说明该连接正在经历重传。我一般这样用:

# 每 5 秒刷新一次,只看有重传的连接
watch -n 5 'ss -t -i | grep -v "retrans:0/"'

这样就能实时监控哪些连接在重传。配合 grep 过滤出非零值,一目了然。

4.3.3 netstat -s 看全局重传率

有时候单个连接看不出问题,但整体重传率偏高。这时候用 netstat -s:

# 只看 TCP 部分
netstat -st | grep -E "retrans|reorder|loss"

# 输出示例
    12345 segments retransmitted
    5678 fast retransmits
    234 retransmits in slow start
    890 lost packets
    3456 packets reordered

重传率 = 重传段数 / 总发送段数。一般超过 1% 就要警惕了。我见过一个极端案例,重传率到 15%,最后发现是网卡固件 bug。

我的排查顺序:先 netstat -s 看全局重传率 → 如果偏高,用 ss -t -i 找出具体连接 → 再用 tcpdump 抓那个连接的包 → 最后 Wireshark 分析重传类型。每一步都有明确目的,不盲目抓包。

4.4 三件套协同工作流程图

下面这张图总结了我日常排查重传的完整流程。从怀疑有重传开始,到定位根因,每一步用什么工具、看什么指标,都画清楚了。

重传定位三件套协同流程图 重传定位三件套协同流程图 怀疑有 TCP 重传 第一步:netstat -s 看全局重传率 重传率 > 1% ? 确认问题范围 第二步:ss -t -i 找出重传连接 关注 retrans 字段,过滤非零连接 第三步:tcpdump 抓目标连接流量 -s 0 -w file.pcap host IP and port PORT 第四步:Wireshark 精确定位重传类型 过滤:tcp.analysis.retransmission 区分超时重传 vs 快速重传 定位根因:丢包/拥塞/乱序/配置 关键指标参考 • 重传率 < 0.5%:正常 • 重传率 0.5%~1%:需关注 • 重传率 > 1%:必须排查 • 快速重传占比高:乱序 • 超时重传占比高:拥塞 • retrans 持续增长:有问题

4.5 实战案例:一次完整的重传定位

最后分享一个真实案例。有一次线上告警说接口响应变慢,我按上面的流程走了一遍:

  1. netstat -s 发现重传率 3.2%,明显异常。
  2. ss -t -i 看到有 5 个连接 retrans 值在增长,目标都是同一台数据库服务器。
  3. tcpdump 抓了 30 秒的包,保存到 pcap。
  4. Wireshark 打开一看,全是 TCP Fast Retransmission,间隔非常规律——每 10ms 一次。

为什么规律?我查了数据库服务器的网卡,发现开启了 TCP 分段卸载(TSO),但交换机不支持巨型帧。TSO 把大包分片后,交换机直接丢弃了部分分片,导致接收端收到乱序包,触发快速重传。关闭 TSO 后,重传率降到 0.1%。

避坑指南:我曾经在排查时只看了 Wireshark 的重传标记,没看连接状态。结果发现重传标记很多,但 ss 显示 retrans 为 0——因为抓包点在中间路径,Wireshark 误判了。所以一定要结合 ss 的 retrans 字段交叉验证。

嗯,工具说到底只是手段。关键是理解每个工具能告诉你什么,以及怎么串联起来。tcpdump 给你原始数据,Wireshark 帮你分类,ss/netstat 给你实时状态。三件套用熟了,重传定位就是走流程的事。