问题现象
业务层面感知:应用程序出现网络超时、连接中断或数据传输失败。
系统层面丢包:通过
cat命令持续观察/proc/net/softnet_stat文件时,发现第二列(dropped)或第三列(squeezed)的计数值持续快速增长。# 每一行对应一个CPU核心。 # 第一列:收到的网络帧总数。 # 第二列:因为backlog队列满而被丢弃的数据包数 (dropped)。 # 第三列:因为处理时间耗尽而延迟处理的数据包数 (squeezed)。 $ cat /proc/net/softnet_stat 000bb344 00000471 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 000bc76f 00000305 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001CPU软中断高:使用
top或mpstat等工具,观察到si(softirq)的CPU使用率异常高。
问题原因
当网卡驱动收到数据包后,会通过软中断(NET_RX_SOFTIRQ)通知内核协议栈处理。为缓冲突发流量,内核为每个CPU核心维护了一个softnet backlog队列。丢包主要由以下两个原因引起:
softnetbacklog队列过小:在高网络吞吐场景下,如果数据包进入队列的速率持续高于CPU处理速率,队列会很快被填满。此时,新到达的数据包将被直接丢弃,导致/proc/net/softnet_stat文件中第二列的dropped计数增加。CPU处理能力不足:即使队列大小充足,但如果CPU核心无法在分配的时间预算内(
net.core.netdev_budget)完成对softnetbacklog队列中数据包的处理,也会导致处理中断。这种情况被称为time_squeeze,会导致/proc/net/softnet_stat文件中第三列的squeezed计数增加。这表明瓶颈在于CPU算力,而非队列大小。
解决方案
首先通过监控/proc/net/softnet_stat的动态变化,判断丢包是由于队列大小不足(dropped增加)还是CPU处理瓶颈(squeezed增加),然后采取针对性的优化措施。
步骤一:诊断丢包根本原因
实时监控softnet状态,区分是dropped问题还是squeezed问题。
登录ECS Linux实例。
执行以下命令,每秒刷新一次
softnet的统计数据,重点关注dropped和squeezed列的增量。/proc/net/softnet_stat中的计数值是自系统启动以来的累计值。仅当观察到数值持续快速增长时,才表明当前存在问题。watch -d 'awk "{print \"CPU\"(NR-1)\": dropped=\"\$2\", squeezed=\"\$3}" /proc/net/softnet_stat'根据命令输出结果,判断问题类型:
dropped列持续增长,squeezed列基本不变:表明问题是softnetbacklog队列过小。请执行步骤二:调整backlog队列大小。squeezed列持续增长(无论dropped是否增长):表明问题是CPU处理能力成为瓶颈。请执行步骤三:优化CPU处理能力。
步骤二:调整backlog队列大小
通过调大net.core.netdev_max_backlog参数,可以增加队列容量,缓解因突发流量导致的丢包问题。
执行以下命令查看当前的
netdev_max_backlog值。默认值通常为1000。sysctl net.core.netdev_max_backlog根据实例网络带宽,参考下表设置一个合理的
netdev_max_backlog值。重要:不合理的巨大数值会增加内存消耗并可能引入网络延迟,请谨慎设置。 内存占用估算公式:
内存占用(Bytes) ≈ netdev_max_backlog × 平均包长 × CPU核心数。设置的大小主要取决于你的网络带宽和业务场景。
业务场景
带宽环境
推荐值
说明
默认/低配
1Gbps
1000(默认)
默认值通常为 1000,对于普通流量够用。
中等负载
1Gbps ~ 10Gbps
5000 ~ 10000
适用于大部分标准 Web 服务器、应用服务器。
高并发/高吞吐
10Gbps
30000
适用于 Nginx 网关、Redis、高频 API 服务。
极高性能
40Gbps+
60000 ~ 100000
适用于核心交换节点、DDoS 清洗、超高频交易系统。
临时修改参数值使其立即生效。请将
NETDEV_MAX_BACKLOG_NUMBER替换为实际规划的数值。sysctl -w net.core.netdev_max_backlog=NETDEV_MAX_BACKLOG_NUMBER为确保服务器重启后配置依然生效,需要将配置持久化。
方法一:推荐 创建或修改
/etc/sysctl.d/99-network-tuning.conf文件,并加入以下内容:# Increase kernel softnet backlog queue size net.core.netdev_max_backlog = NETDEV_MAX_BACKLOG_NUMBER方法二: 在
/etc/sysctl.conf文件末尾添加以下内容:net.core.netdev_max_backlog = NETDEV_MAX_BACKLOG_NUMBER然后执行
sysctl -p使配置生效。
返回步骤一,重新观察
dropped计数是否停止增长,以验证优化效果。
步骤三:优化CPU处理能力
利用多核CPU并行处理网络软中断,即启用RPS(Receive Packet Steering)。
确认实例拥有vCPU数量。RPS在单核实例上无效。
找到需要优化的网卡名称,通常为
eth0或eth1。启用RPS,将网络软中断分发到所有CPU核心进行处理。
rps_cpus的值是一个CPU位掩码。例如,一个8核CPU的掩码是ff(二进制11111111),16核是ffff。可以根据CPU核心数计算,或直接使用一个足够大的值(如ffffffff)来覆盖所有核心。# 将<interface>替换为网卡名,例如eth0 # 将<cpu_mask>替换为计算出的CPU掩码,例如ff (8核) echo <cpu_mask> > /sys/class/net/<interface>/queues/rx-0/rps_cpus # 示例:为8核CPU的eth0网卡启用RPS echo ff > /sys/class/net/eth0/queues/rx-0/rps_cpus为使配置在重启后依然生效,需要将上述命令添加到启动脚本中,例如
/etc/rc.local。返回步骤一,重新观察
squeezed计数是否停止增长,以验证优化效果。
后续建议
设置监控告警:在阿里云云监控中,为ECS实例配置自定义监控项,监控
/proc/net/softnet_stat中dropped和squeezed的增长率,并设置告警规则,以便在问题发生时第一时间收到通知。选择合适的实例规格:对于网络密集型应用,推荐选用网络增强型实例规格(如c7ne、g7ne等),它们提供更高的网络PPS(包转发率)和带宽性能。