服务器网卡丢包怎么排查?网卡统计、驱动与交换网络分析

网络"时快时慢""偶尔超时""大文件传一半断了",很多情况下根子在丢包。丢包有个讨厌的地方:它不一定表现为完全不通,而是让 TCP 反复重传、应用响应忽快忽慢,用户体感是"网卡住了但又能用",排查时很容易误判成应用问题。要抓住它,必须从网卡自己的统计计数器开始。

这篇文章讲一套自下而上的网卡丢包排查方法:先读懂 ip -s link 的收发计数,区分丢包发生在发送侧还是接收侧;再用 ethtool 看驱动和链路层参数;然后向上延伸到交换机/云网络的排查;最后给出常见的调优项和风险提示。读完之后,你应该能从一堆计数器里迅速判断"包是在服务器里丢的,还是在服务器外的网络里丢的"。

需要明确一个前提:服务器侧能看到的丢包统计,只覆盖它自己网卡层面发生的事。如果丢包发生在中间的交换机、路由器或云网络上,服务器计数器往往是干净的,这时候要靠双向测试和抓包来推断。所以排查思路必须是"先分清责任边界"。

一、先读懂网卡的收发计数器

排查丢包第一步永远是看网卡统计,命令是 ip -s link(老命令是 ifconfig -a 或 netstat -i)。

# 查看指定网卡的详细统计
ip -s link show eth0
ip -s -s link show eth0       # 加第二个 -s 显示更详细的错误分类

# 实时观察计数变化(每 1 秒刷新,重点看哪些数字在涨)
watch -n 1 'ip -s link show eth0'

# 老命令(net-tools)
netstat -i
ifconfig eth0

ip -s -s link show eth0 的关键字段和含义:

字段 所在段 含义 异常含义
RX packets 接收 收到的包数 数量正常即可
RX errors 接收 接收错误总数 帧校验错、硬件问题
RX dropped 接收 接收侧丢弃 缓冲不足或协议栈丢弃
RX overrun 接收 环形缓冲溢出 收包太快,网卡来不及处理
RX frame 接收 帧对齐/长度错误 网线、双工、硬件
TX packets 发送 发送的包数 —
TX errors 发送 发送错误总数 硬件或链路问题
TX dropped 发送 发送侧丢弃 队列满、虚拟化环境常见
TX carrier 发送 载波错误 链路闪断、网线/光模块问题
collisions 发送 冲突计数 半双工环境下才有意义

判读的逻辑是:看哪个计数器在持续增长。用一个基线对比法最有效——先记录一次,等几分钟再记录一次,看增量。

# 采集两次样本对比增量
ip -s link show eth0 > /tmp/link1.txt
sleep 60
ip -s link show eth0 > /tmp/link2.txt
diff /tmp/link1.txt /tmp/link2.txt

如果 RX errors、RX dropped 在涨,说明接收侧有问题;如果 TX 的 dropped/carrier 在涨,说明发送侧有问题。分清方向是后续排查的分水岭。

二、发送侧丢包:多为队列和虚拟化问题

发送侧(TX)丢包在虚拟机和容器环境里尤其常见,原因往往是内核发包速度超过了底层能处理的速度。

# 查看发送队列长度和排队规则
ip -s link show eth0
tc -s qdisc show dev eth0

# 查看网卡驱动层的队列信息
ethtool -S eth0 | grep -iE 'tx|drop|queue'

# 查看队列满导致的丢弃统计
ethtool -S eth0 | grep -iE 'tx_errors|tx_dropped|tx_aborted'

发送侧丢包的常见原因:

  • 发送队列太小或 qdisc 排队过多:高并发小包场景下,tc 的队列会积压。可用 tc qdisc 查看 backlog,必要时调整 txqueuelen(ip link set eth0 txqueuelen 1000)。
  • 虚拟化平台的 TX dropped 是正常现象:KVM/Xen 虚拟机的 TX dropped 常常反映了宿主机的限流或半虚拟化网卡的处理能力,不一定代表故障。但持续大量增长要提高警惕。
  • 网卡硬件队列不足:单队列网卡在多核高并发下容易成为瓶颈,可用 ethtool -l eth0 查看队列数,支持多队列(RSS)的网卡可调大。

一个实用命令是 ethtool -S,它会输出驱动级别的所有计数器,不同驱动的字段名不一样,但常见的 tx_dropped、rx_missed_errors、rx_no_buffer_count 等含义相近:

# 列出驱动统计(不同网卡字段不同,grep 关键字)
ethtool -S eth0 | grep -iE 'drop|miss|error|no_buffer|fifo'

# 查看队列数量
ethtool -l eth0
ethtool -g eth0        # 查看环形缓冲区大小

三、接收侧丢包:先看环形缓冲与中断

接收侧(RX)丢包的根源通常是"包来得太快,内核处理不过来"。数据从网卡到内核要经过环形缓冲区(ring buffer)和中断处理,任何一环跟不上都会丢包。

# 查看环形缓冲区大小(当前值 vs 最大值)
ethtool -g eth0

# 临时调大环形缓冲区到最大值(可能提升接收能力,占用更多内存)
ethtool -G eth0 rx 4096 tx 4096

# 查看中断分布,判断是否所有中断都压在一个 CPU 上
cat /proc/interrupts | grep -i eth0
mpstat -P ALL 1 3          # 需 sysstat 包

# 查看软中断统计(NET_RX 过高说明网络收包压力大)
cat /proc/softirqs | grep -i net

典型的"接收丢包"案情:单队列网卡,所有网络中断都落到 CPU0,收包量大时 CPU0 被软中断打满,其他核闲着,ip -s link 的 RX dropped 持续增长。解决办法是启用多队列(RSS)并配合 irqbalance 或手动绑定中断到多个 CPU,或者用 RPS/RFS(多队列软件实现)。

# 查看是否启用了 RPS(软件多队列)
cat /sys/class/net/eth0/queues/rx-0/rps_cpus
# 例如设置为所有 CPU(十六进制掩码,0xf 表示 CPU0-3)
echo f > /sys/class/net/eth0/queues/rx-0/rps_cpus

# 安装并启用 irqbalance 自动分散中断
# RHEL/CentOS/Rocky
yum install -y irqbalance   # 或 dnf
systemctl enable --now irqbalance
# Debian/Ubuntu
apt install -y irqbalance
systemctl enable --now irqbalance

环形缓冲、多队列、RPS 这些是接收侧调优的主要手段,但要注意:调大环形缓冲会增加内存占用和延迟,多队列需要网卡和驱动支持,调整前先确认硬件能力。

四、向上排查:交换机与云网络

如果服务器侧的 RX/TX 计数器都很干净,但业务确实在丢包,那么问题很可能在服务器之外的网络设备上,也可能是物理链路问题。

# 1. 物理层检查:网线、光模块、双工模式
ethtool eth0
# 关注 Speed(协商速率)、Duplex(全双工/半双工)、Link detected

# 2. 强制全双工(如果是双工不匹配导致大量 collisions)
# 注意:需要交换机侧同步设置,否则可能更糟
ethtool -s eth0 speed 1000 duplex full autoneg off

# 3. 链路错误统计
ethtool -S eth0 | grep -iE 'crc|align|fcs|carrier'

# 4. 网关丢包测试(判断丢包是本地还是上游)
ping -c 100 -i 0.2 192.168.1.1        # 打网关
mtr -rw -c 100 8.8.8.8                # 逐跳看丢包发生在哪一跳

# 5. 双向抓包对比(判断是发丢了还是收丢了)
tcpdump -i eth0 -n -c 100 host 203.0.113.10

关键判据:

  • ethtool eth0 显示 Duplex: Half(半双工),基本可以确定是双工不匹配,会导致大量冲突和丢包,必须两端统一为全双工。
  • Speed 协商成 100M 而链路应该是 1000M,说明网线质量差或接口问题,换线或换端口。
  • ethtool -S 里 rx_crc_errors、rx_frame_errors 持续增长,是物理链路问题(网线、光模块、接头)。
  • mtr 显示丢包从某一跳开始出现、且后续跳都丢,说明问题在那个节点或其后。
  • 抓包显示包发出去了但被对上收到的少了,说明中间网络丢包。

云服务器的情况要单独说:云厂商的网络在虚拟化层做了很多处理,tx_dropped 在新一代虚拟网卡上经常是常态(反映宿主限流),不一定是故障。云上排查丢包要结合:实例的带宽上限、突发积分是否耗尽、安全组是否有丢包策略、以及同可用区还是跨可用区(跨区延迟和丢包通常更高)。这些指标在云控制台的监控里能看到,比自己数计数器更准。

五、应用层视角:丢包如何影响业务

网卡丢包对上层的影响,取决于协议和丢包率。给出一些经验量级供参考(具体视业务而定):

丢包率 TCP 表现 体感
< 0.01% 基本无感知,偶发重传 正常
0.1% 少量重传,吞吐略降 大文件传输变慢
1% 明显重传,吞吐大幅下降 网页加载变慢、偶发超时
5% 频繁超时重传 视频卡顿、连接不稳定
> 10% 大量连接超时中断 基本不可用

TCP 对丢包很敏感,因为一次丢包往往触发拥塞窗口收缩。在高带宽高延迟链路上(BDP 大),1% 丢包就能让吞吐掉到理论值的零头。这也是为什么很多"带宽明明够,就是传不快"的案子,最后查到是丢包。

# 查看 TCP 重传统计
ss -s                                  # 汇总信息
netstat -s | grep -iE 'retrans|timeout'
nstat -az | grep -iE 'Retrans|TCPTimeouts'
# 持续观察重传
watch -n 1 'netstat -s | grep -i retrans'

如果 netstat -s 里的 segments retransmitted 占比持续偏高,就说明链路正在丢包,值得往网络方向深挖。

六、调优建议与风险提示

# 查看/调整网卡参数
ethtool -k eth0                # 查看 offload 特性(校验和、TSO、GRO 等)
ethtool -K eth0 gro on         # 调整 GRO
ethtool -K eth0 tso on

# 调整内核网络缓冲(/etc/sysctl.conf 或 /etc/sysctl.d/*.conf)
# net.core.rmem_max = 16777216
# net.core.wmem_max = 16777216
# net.core.netdev_max_backlog = 5000     # 接收队列积压上限
# net.ipv4.tcp_rmem = 4096 87380 16777216
# net.ipv4.tcp_wmem = 4096 65536 16777216
sysctl -p

风险提示与回滚:

  • ethtool -G 调大环形缓冲会占用内核内存,可能挤压其他用途;改前记录原值(ethtool -g eth0),要回滚就用原值再设一次。
  • ethtool -s 强制速率/双工极其危险:如果交换机侧是自协商而服务器强制,会直接链路不通、服务器失联。远程服务器慎用,且必须两端同步。回滚方式是 ethtool -s eth0 autoneg on 恢复自协商。
  • ethtool -K 关闭 offload 有时能解决虚拟化下的奇怪问题,但要评估 CPU 开销,关闭 TSO/GRO 会显著增加 CPU 占用。
  • 修改 sysctl 网络参数前先 cp /etc/sysctl.conf /etc/sysctl.conf.bak,出问题还原后 sysctl -p。

常见问题

Q:ip -s link 里 RX dropped 一直涨,但业务看起来正常,要紧吗?
要看丢的是什么包。如果丢的是广播、多播或不符合本机地址的包(比如混杂模式下的杂包),业务正常就无需处理。如果丢的是正常单播且量在涨,就要查环形缓冲、CPU 软中断和上层协议栈。

Q:怎么区分是服务器丢的包还是网络丢的包?
在服务器出口抓包(tcpdump -i eth0)记录发出的包数,在对端抓包记录收到的包数,两边一对比,差值就是中间网络丢的。服务器侧计数器干净、但对端收不全,责任就在网络。

Q:ethtool -S 输出字段太多看不懂,先看哪几个?
先 grep 这几类:drop、miss、error、buffer、fifo、crc。其中 rx_missed_errors、rx_no_buffer_count 指向接收缓冲不足,rx_crc_errors 指向物理链路,tx_dropped 指向发送队列或虚拟化限流。

Q:虚拟机上 TX dropped 一直在涨,是不是有问题?
在 KVM/Xen 等虚拟化环境下,TX dropped 很多时候反映的是宿主机侧的限流或半虚拟化网卡的处理策略,属于常见现象。要结合业务是否真的受损来判断;如果业务正常、延迟稳定,可以观察而不必处理。

Q:ping 大包丢、小包不丢,是丢包吗?
这通常是 MTU 或路径 MTU 的问题,不是传统意义的丢包。大包需要在中间设备分片或被丢弃,表现出来就是"小包能通、大包不通"。查 MTU 用 ping -M do -s 1472,具体方法见 MTU 相关主题。

总结

网卡丢包排查从 ip -s link(或 ip -s -s link)开始,先分清是接收侧丢还是发送侧丢,看哪个计数器在持续增长,这是整个排查的起点。

接收侧丢包多是环形缓冲不足、单队列 CPU 瓶颈、软中断打满,调优手段是 ethtool -G 调大 ring buffer、启用多队列与 irqbalance、配置 RPS。

发送侧丢包在虚拟化环境常见,先看 txqueuelen、qdisc backlog 和 ethtool -S 的 tx 类计数,不要一看到 TX dropped 就当成故障。

服务器计数器干净但业务在丢包时,向网络侧排查:用 ethtool 查双工/速率/CRC,用 mtr 定位丢包跳数,用双向抓包判断责任边界;云上还要结合带宽上限和突发积分看。

丢包对 TCP 影响很大,用 netstat -s/ss -s 看重传率评估影响;所有调优操作(尤其 ethtool -s 强制速率双工)都要先记录原值、评估风险、准备回滚,远程服务器慎改链路参数。