34.2. 调优 IRQ 平衡
在多核主机上,您可以通过确保 Red Hat Enterprise Linux 平衡中断队列(IRQ)来在 CPU 核之间分发中断来提高性能。
34.2.1. 中断和中断处理程序
当网络接口控制器(NIC)接收传入数据时,它会使用直接内存访问(DMA)将数据复制到内核缓冲区中。然后,NIC 通过触发一个硬中断来向内核通知此数据。这些中断是由中断处理程序处理的,这些处理程序只做最少的工作,因为它们已中断了另一个任务,处理程序不能中断自己。硬中断在 CPU 使用率方面可能代价高昂,特别是在使用内核锁时。
然后,硬中断处理器将大多数接收的数据包留给软件中断请求(SoftIRQ)进程。内核可以更公平地调度这些进程。
例 34.1. 显示硬件中断
内核将中断计数存储在 /proc/interrupts
文件中。要显示特定 NIC 的计数,如 enp1s0
,请输入:
# egrep "CPU|enp1s0" /proc/interrupts CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 105: 141606 0 0 0 0 0 IR-PCI-MSI-edge enp1s0-rx-0 106: 0 141091 0 0 0 0 IR-PCI-MSI-edge enp1s0-rx-1 107: 2 0 163785 0 0 0 IR-PCI-MSI-edge enp1s0-rx-2 108: 3 0 0 194370 0 0 IR-PCI-MSI-edge enp1s0-rx-3 109: 0 0 0 0 0 0 IR-PCI-MSI-edge enp1s0-tx
每个队列在分配给它的第一列中有一个中断向量。当系统引导时,或者用户载入 NIC 驱动程序模块时,内核会初始化这些向量。会给每个接收(RX
)和传输(TX
)队列分配一个唯一的向量,其告知中断处理程序中断来自哪个 NIC 或队列。列代表每个 CPU 核的传入中断数。
34.2.2. 软件中断请求
软件中断请求(SoftIRQ)清除网络适配器的接收环缓冲。内核调度 SoftIRQ 例程在其他任务没有被中断的时侯运行。在 Red Hat Enterprise Linux 上,名为 ksoftirqd/cpu-number
的进程运行这些例程,并调用特定于驱动程序的代码函数。
要监控每个 CPU 内核的 SoftIRQ 计数,请输入:
# watch -n1 'egrep "CPU|NET_RX|NET_TX" /proc/softirqs'
CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7
NET_TX: 49672 52610 28175 97288 12633 19843 18746 220689
NET_RX: 96 1615 789 46 31 1735 1315 470798
命令会动态更新输出。按 Ctrl+C 中断输出。
34.2.3. NAPI 轮询
新的 API (NAPI)是设备驱动程序数据包处理框架的扩展,以提高传入网络数据包的效率。硬中断非常昂贵,因为它们通常会导致上下文从内核空间切换到用户空间,然后再切换回来,并且不能中断自己。即使中断合并,中断处理器也会完全垄断一个 CPU 核。使用 NAPI ,驱动程序可以使用轮询模式,而不是内核为接收的每个数据包进行硬中断。
在正常操作下,内核会发出一个初始硬中断,后跟一个软中断请求(SoftIRQ)处理程序,该处理程序使用 NAPI 例程轮询网卡。为防止 SoftIRQ 垄断一个 CPU 核,轮询例程有一个确定 SoftIRQ 可以使用的 CPU 时间的预算。完成 SoftIRQ 轮询例程后,内核会退出例程,并将其安排在稍后运行,以重复从网卡接收数据包的过程。
34.2.4. irqbalance 服务
在具有和不具有非统一内存访问(NUMA)架构的系统上,irqbalance
服务根据系统状况有效地平衡跨 CPU 核的中断。irqbalance
服务在后台运行,每 10 秒监控一次 CPU 负载。当 CPU 的负载过高时,服务会将中断移到其他 CPU 核。因此,该系统表现良好,并更有效地处理负载。
如果 irqbalance
没有运行,则 CPU 核 0 通常会处理大多数中断。即使在中等负载下,这个 CPU 核可能会变得非常忙碌,试图处理系统中所有硬件的工作负载。因此,中断或基于中断的工作可能会丢失或延迟。这可能导致网络和存储性能较低、数据包丢失以及其他潜在的问题。
禁用 irqbalance
可能会对网络吞吐量造成负面影响。
在只有一个 CPU 核的系统上,irqbalance
服务不提供任何好处,并自行退出。
默认情况下,irqbalance
服务在 Red Hat Enterprise Linux 上启用并运行。要重新启用该服务(如果您禁用了它),请输入:
# systemctl enable --now irqbalance
其他资源
- 是否需要 irqbalance? 解决方案
- 我应该如何配置网络接口 IRQ 通道? 解决方案
34.2.5. 增加 SoftIRQ 可在 CPU 上运行的时间
如果 SoftIRQ 没有运行足够长时间,则传入数据的速度可能会超过内核快速排空缓冲区的能力。因此,网络接口控制器(NIC)缓冲区溢出,数据包丢失。
如果 softirqd
进程无法在一个 NAPI 轮询周期中检索来自接口的所有数据包,则表示 SoftIRQ 没有足够的 CPU 时间。这种情况可能出现在具有快速 NIC 的主机上,如 10 Gbps 和更快。如果您增加了 net.core.netdev_budget
和 net.core.netdev_budget_usecs
内核参数的值,则您可以控制 softirqd
在一个轮询周期内处理数据包的时间和数量。
流程
要确定是否需要调整
net.core.netdev_budget
参数,请显示/proc/net/softnet_stat
文件中的计数:# awk '{for (i=1; i<=NF; i++) printf strtonum("0x" $i) (i==NF?"\n":" ")}' /proc/net/softnet_stat | column -t 221951548 0 0 0 0 0 0 0 0 0 0 0 0 192058677 0 20380 0 0 0 0 0 0 0 0 0 1 455324886 0 0 0 0 0 0 0 0 0 0 0 2 ...
此
awk
命令将/proc/net/softnet_stat
中的值从十六进制转换为十进制格式,并以表格式显示它们。每行代表核 0 开始的 CPU 核。相关的列有:
- 第一列:收到的总帧数。
-
第三列:
softirqd
进程不能在一个 NAPI 轮询周期中检索来自接口的所有数据包的次数。 - 最后一列:CPU 核号。
如果
/proc/net/softnet_stat
文件的第三列中的计数随着时间而递增,请调优系统:显示
net.core.netdev_budget_usecs
和net.core.netdev_budget
参数的当前值:# sysctl net.core.netdev_budget_usecs net.core.netdev_budget net.core.netdev_budget_usecs = 2000 net.core.netdev_budget = 300
使用这些设置,
softirqd
进程在一个轮询周期内最多有 2000 微秒来处理最多 300 个来自 NIC 的消息。轮询根据首先满足哪个条件而结束。使用以下内容创建
/etc/sysctl.d/10-netdev_budget.conf
文件:net.core.netdev_budget = 600 net.core.netdev_budget_usecs = 4000
将参数设置为其当前值的两倍。
从
/etc/sysctl.d/10-netdev_budget.conf
文件中加载设置:# sysctl -p /etc/sysctl.d/10-netdev_budget.conf
验证
监控
/proc/net/softnet_stat
文件中的第三列:# awk '{for (i=1; i<=NF; i++) printf strtonum("0x" $i) (i==NF?"\n":" ")}' /proc/net/softnet_stat | column -t
如果值还在增加,请将
net.core.netdev_budget_usecs
和net.core.netdev_budget
设置为更高的值。重复此过程,直到计数不再增加。