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 三件套协同工作流程图
下面这张图总结了我日常排查重传的完整流程。从怀疑有重传开始,到定位根因,每一步用什么工具、看什么指标,都画清楚了。
4.5 实战案例:一次完整的重传定位
最后分享一个真实案例。有一次线上告警说接口响应变慢,我按上面的流程走了一遍:
- netstat -s 发现重传率 3.2%,明显异常。
- ss -t -i 看到有 5 个连接 retrans 值在增长,目标都是同一台数据库服务器。
- tcpdump 抓了 30 秒的包,保存到 pcap。
- Wireshark 打开一看,全是
TCP Fast Retransmission,间隔非常规律——每 10ms 一次。
为什么规律?我查了数据库服务器的网卡,发现开启了 TCP 分段卸载(TSO),但交换机不支持巨型帧。TSO 把大包分片后,交换机直接丢弃了部分分片,导致接收端收到乱序包,触发快速重传。关闭 TSO 后,重传率降到 0.1%。
避坑指南:我曾经在排查时只看了 Wireshark 的重传标记,没看连接状态。结果发现重传标记很多,但 ss 显示 retrans 为 0——因为抓包点在中间路径,Wireshark 误判了。所以一定要结合 ss 的 retrans 字段交叉验证。
嗯,工具说到底只是手段。关键是理解每个工具能告诉你什么,以及怎么串联起来。tcpdump 给你原始数据,Wireshark 帮你分类,ss/netstat 给你实时状态。三件套用熟了,重传定位就是走流程的事。