SMP IRQ affinity允许系统限制或者重新分配服务器的工作负载, 从而让服务器更有效的工作。以网卡中断为例,在没有设置SMP IRQ affinity时, 所有网卡中断都关联到CPU0, 这导致了CPU0负载过高,而无法有效快速地处理网络数据包,容易产生性能瓶颈。通过SMP IRQ affinity,把网卡多个中断分配到多个CPU上,可以分散CPU压力,提高数据处理速度。
图1 SMP对称多处理器结构
同时,Linux的irqbalance用于优化中断分配,自动收集系统数据以分析使用模式,并依据系统负载状况将工作状态置于Performance Mode或Power-Save Mode。处于Performance Mode时irqbalance会将中断尽可能均匀地分发给各个CPU以充分利用CPU多核,提升性能;处于Power-Save Mode时,irqbalance会将中断集中分配给第一个CPU,以保证其它空闲CPU的睡眠时间,降低能耗。
正常情况下,一张网卡只有一个队列用来接收网络数据包时,同一时间数据包的处理只能由某个单核处理,不仅无法发挥多CPU多核优势,而且大流量带宽下必然造成数据包阻塞。因此,随着技术的发展,引入了网卡多队列机制,一张网卡支持多个队列来接发收数据包,这样同一时间多个队列的数据包可以分散到不同的CPU进行处理。RSS(Receive Side Scaling)是网卡的硬件特性,实现多队列,每个队列对应一个中断号,通过中断绑定实现网卡中断在多CPU多核上的分配。
但是在网络压力较大时,多队列网卡I/O产生的中断访问非常多,此时队列数量会对网卡数据包的处理效率产生较大影响。根据实践经验,当单个PCIe槽位上网卡的队列总数等于该PCIe槽位所连接的CPU物理核数时,网卡I/O中断的处理效率将会最高。例如,单颗CPU的物理核心数为32,每张网卡的端口为2,所以网卡的多队列数应设置为16=32/2。
由于操作系统默认通过irqbalance服务来分派网卡队列中的网络数据包交由哪个CPU core处理,当irqbalance服务分配的处理网卡中断的CPU core不是网卡PCIe槽位所连接的CPU die或CPU时,会触发跨CPU die或CPU的core访问,中断处理效率会比较低。因此,在网卡队列数设置完成后,我们还需要关闭irqbalance服务,将网卡队列中断号绑定到处理网卡中断的CPU core上,从而减少跨CPU die或CPU访问所带来的额外开销,进一步提升网络处理性能。
#02、动手实践
判断当前系统环境是否支持多队列网卡。
# lspci -vvv |
如果在Ethernet项中含有MSI-X: Enable+ Count=9 Masked-语句,则说明当前系统环境是支持多队列网卡的,否则不支持。
查看网卡是否支持多队列,以及最多支持多少、当前开启多少。
# ethtool -l eth0 ## 查看 eth0 多队列情况 |
设置网卡当前使用多队列。
# ethtool -L eth0 combined ## 针对 eth0 网卡设置多队列,N为要设置的队列数 |
确保多队列设置确实已生效,可以查看文件。
# ls /sys/class/net/eth0/queues/ ## 确认rx数量等于设定值 rx-0 rx-2 rx-4 rx-6 tx-0 tx-2 tx-4 tx-6 |
查看系统给网卡端口分配的中断号。
# cat /proc/interrupts | grep –i eth0 |
主动关闭irqbalance进程。
# service irqbalance stop |
更新文件,设置中断绑定。
通过修改或可以设置中断绑定,其中{IRQ_ID}是相应的中断号。smp_affinity内容是16进制,smp_affinity_list内容是10进制,两个文件相通,修改一个之后另一个相应改变。
#03、经验总结
可以通过手动改变smp_affinity文件中的值来将IRQ绑定到指定的CPU核心上,或者启用irqbalance服务来自动绑定IRQ到CPU核心上。针对多CPU多核的SMP体系,一般默认启用irqbalance简化配置并保障性能。
对于文件服务器、高流量Web服务器这样的应用来说,把不同的网卡IRQ均衡绑定到不同的CPU上将会减轻某个CPU的负担,提高多个CPU整体处理中断的能力。
对于数据库服务器这样的应用来说,把磁盘控制器绑到一个CPU、把网卡绑定到另一个CPU将会提高数据库的响应时间实现优化性能。
综上所述,性能优化是一个过程而不是结果,需要大量的测试、观察、验证和改进。因此,应用系统需要合理地根据生产环境配置和应用特点来平衡IRQ中断,从而不断提高系统的整体吞吐能力和性能。