[Linux性能调优] 网卡中断与CPU的绑定问题

背景

网卡与操作系统的交互一般有两种方式:

  • 一种是中断(IRQ,网卡在收到了网络信号之后,主动发送中断到CPU,而CPU将会立即停下手边的活以便对这个中断信号进行分析)
  • 另一种叫DMA(Direct Memory Access, 也就是允许硬件在无CPU干预的情况下将数据缓存在指定的内存空间内,在CPU合适的时候才处理)
    目前在实际生产中,服务器还使用的中断方式 ,据说DMA方式会使外部设备的控制器独占PCI总线,从而CPU无法与外部设备进行交互,这对通用型操作系统Linux来说,是很难接受的,所以DMA方式在Linux内核里使用得很少。

问题判定

当出现CPU占用不均的时候,就需要考虑网卡多队列是否尚未与CPU绑定引起的?

1
2
3
4
5
6
7
mpstat -P ALL 1
18:20:33     CPU   %user   %nice    %sys %iowait    %irq   %soft  %steal   %idle    intr/s
18:20:33     all    0,23    0,00    0,08    0,11    6,41    0,02    0,00   93,16   2149,29
18:20:33       0    0,25    0,00    0,12    0,07    0,01    0,05    0,00   99,49    127,08
18:20:33       1    0,14    0,00    0,03    0,04    0,00    0,00    0,00   99,78      0,00
18:20:33       2    0,23    0,00    0,02    0,03    0,00    0,00    0,00   99,72      0,02
18:20:33       3    0,28    0,00    0,15    0,28   25,63    0,03    0,00   73,64   2022,19
  1. 查看设备硬件是否支持网卡多队列
    #lspci -vvv
    Ethernet controller的条目内容,如果有MSI-X && Enable+ && TabSize > 1,则该网卡是多队列网卡
    在这里插入图片描述
  2. 查看是否打开网卡多队列
    cat /etc/modprobe.conf查看网卡驱动。

broadcom网卡的驱动为e1000,默认打开网卡多队列
在这里插入图片描述
intel网卡的驱动为igb,默认不打开网卡多队列,需要添加options igb RSS=8,8(不同网卡之间的配置用“逗号”隔开)。
在这里插入图片描述
cat /proc/interrupt | grep eth,观察产生了8个网卡对列,并且对应着不同的中断,即已经打开。
在这里插入图片描述
3. 设置中断亲和性:

将中断52-59分别绑定到CPU0-7上。

1
2
3
4
5
6
7
8
9
10
11
12
13
echo "1" > /proc/irq/52/smp_affinity
echo "2" > /proc/irq/53/smp_affinity
echo "4" > /proc/irq/54/smp_affinity
echo "8" > /proc/irq/55/smp_affinity
echo "10" > /proc/irq/56/smp_affinity
echo "20" > /proc/irq/57/smp_affinity
echo "40" > /proc/irq/58/smp_affinity
echo "80" > /proc/irq/59/smp_affinity

      /proc/irq/${IRQ_NUM}/smp_affinity为中断号为IRQ_NUM的中断绑定的CPU核的情况。以十六进制表示,每一位代表一个CPU核。
        1(00000001)代表CPU0
        2(00000010)代表CPU1
        3(00000011)代表CPU0和CPU1

当网卡多对列大于32时,需要每8位中间使用“,”分隔,如下所示

1
2
3
4
5
6
7
00,00000001
00,00000002
00,00000004
00,00000008
00,00000010
00,00000020
00,00000040

注意:

  1. 使用网卡中断绑定时,切记需要关闭系统中断systemctl stop irqbalance
  2. 生产中虚拟机可能存在无法提供与CPU数目相同的网卡中断,可以考虑采用系统中断,启动命令:
    systemctl start irqbalance