背景

网络丢包是运维中最常见也最棘手的故障之一。大规模集群中,一条丢包记录可能影响数十个业务请求。本文结合实战经验,梳理从链路层到内核协议栈的逐级排查思路,帮助运维人员在复杂环境中快速定位根因。

一、发现丢包——从告警和监控入手

丢包通常不会直接报警,而是隐藏在以下监控指标中:

  • 网卡层面ifconfigip -s link 中的 RX errorsRX droppedTX dropped
  • TCP层面netstat -s 中的 segments retransmittedpackets pruned from receive queue
  • 应用层面:业务日志中的超时、大量 connection reset 错误

建议在 Prometheus 中对 node_network_receive_packets_totalnode_network_transmit_packets_total 做差分监控,一旦出现负增长(业务正常时通常为正),立即触发告警。

二、快速定位——网卡和驱动层

1. ethtool 基础检查

1
2
3
4
5
# 查看网卡基本信息
ethtool eth0

# 查看统计信息(最关键)
ethtool -S eth0

重点关注以下计数器:

计数器 含义
rx_fifo_errors FIFO溢出,接收侧处理慢于网卡速率
tx_fifo_errors 发送FIFO满,网卡来不及发送
rx_crc_errors CRC校验失败,物理链路存在干扰
rx_missed_errors 驱动层缓冲区满,内核未及时读取
collisions CSMA/CD冲突,通常在半双工环境下

2. 确认协商速率与双工模式

1
ethtool eth0 | grep -E 'Speed|Duplex'

速率不匹配(如一端1000M另一端100M)或双工模式不一致(half/full duplex mismatch)是丢包的高发原因。若发现不一致,手动指定:

1
ethtool -s eth0 speed 1000 duplex full autoneg off

3. 网卡缓冲区调整

网卡FIFO/队列过小会导致高速流量溢出:

1
2
3
4
5
# 查看当前环形缓冲区大小
ethtool -g eth0

# 增大Ring Buffer(需驱动支持)
ethtool -G eth0 rx 4096 tx 4096

三、内核协议栈层——软中断与队列

1. 确认软中断是否均衡

1
cat /proc/interrupts | grep eth0

若单核软中断过高(softirq 占比超过 30%),说明中断处理集中在少数CPU核,导致处理瓶颈:

1
2
# 查看各CPU核的软中断分布
mpstat -P ALL 1

若不均衡,可通过 irqbalance 或手动绑核优化:

1
2
3
# 将网卡中断绑定到CPU 0和1
grep eth0 /proc/interrupts | awk -F: '{print $1}' | xargs -I{} \
echo {} > /proc/irq/{}/smp_affinity_list

2. 检查内核缓冲区

1
2
3
4
5
# 接收队列溢出
sysctl net.core.netdev_max_backlog

# 增大接收队列深度(临时)
sysctl -w net.core.netdev_max_backlog=50000

将配置写入 /etc/sysctl.conf 以持久化:

1
2
3
net.core.netdev_max_backlog = 50000
net.core.rmem_max = 268435456
net.core.rmem_default = 16777216

3. conntrack相关丢包(NAT/防火墙场景)

在高并发NAT环境下,conntrack表满会导致丢包:

1
2
3
4
5
6
# 查看conntrack表使用情况
cat /proc/sys/net/netfilter/nf_conntrack_max
cat /proc/sys/net/netfilter/nf_conntrack_count

# 临时扩容
sysctl -w net.netfilter.nf_conntrack_max=1048576

四、TCP层——拥塞控制与重传

1. 分析重传率

1
netstat -s | grep -i retransmit

若重传率超过 1%,通常说明网络存在丢包或延迟抖动。进一步定位是网络问题还是应用问题:

1
2
3
4
# 在服务器端抓包,分析重传模式
tcpdump -i eth0 -w /tmp/retrans.pcap 'tcp[tcpflags] & tcp-retransmit != 0'

# 用 wireshark 分析:统计 -> TCP Streams -> RTD(往返延迟)直方图

2. 丢包时的内核行为

当网卡检测到丢包(通过802.3 pause frame或buffer full信号),内核会触发:

  • 降低 tcp_rmem[3] 接收窗口
  • 触发 tcp_orphan_retries 关闭空闲连接
  • 调用 tcp_prune_ofo_queue 清理乱序队列

可通过以下指标观察:

1
2
# 查看每分钟的丢包/重传统计
watch -n 1 'netstat -s | grep -E "segments retransmitted|packets pruned"'

五、实战案例:NFS挂载点丢包

故障现象:NFS客户端大量 Stale NFS file handle 错误,IO延迟升高。

排查过程

  1. ethtool -S 发现 rx_fifo_errors 持续增长
  2. 确认交换机侧端口存在双工协商问题(半双工/全双工 mismatch)
  3. 手动指定全双工后,FIFO错误立即清零
  4. 挂载参数增加 rsize=131072,wsize=131072,减少小包IO次数

根因:网卡协商为半双工后,NFS大IO响应包被交换机buffer管理机制丢弃。

六、总结

丢包排查的核心思路是分层递进:从网卡硬件 → 内核队列 → 协议栈,逐层确认计数器增量,找到第一层出现异常的节点。以下是关键命令清单:

1
2
3
4
5
# 一键查看网络丢包相关统计
ethtool -S eth0 | grep -iE 'drop|fifo|error|crc|miss'
netstat -s | grep -iE 'retrans|prune|overflow|drop'
cat /proc/net/softnet_stat | awk '{if($2>0 || $3>0) print}'
sysctl net.core | grep max_backlog

建议将上述排查命令封装为 check_packets_loss.sh,配合cron定期采集基线数据。故障发生时,只需对比基线即可快速定位异常层,缩短MTTR。


本文结合生产环境实战经验编写,适合Linux服务器运维人员参考。