网卡中断负载均衡

 

现实中的问题

随着硬件成本的降低,我们服务器配置也越来越“上流”了,可是单台服务器的包处理能力还是很有限,经常看到cpu负载很高, linux内核自从2.4版本之后就引入了netfilter框架,网络数据包的处理能力很大程度上是以并发连接数来衡量的,每一个连接在内核中实际上是做了很多处理的。特别是有大量udp包处理的情况,这些udp包多是短连接,并发量又大,也就是说对cpu的耗费是非常大的。mpstat -P ALL 1:

我们从图中可以看出cpu0处于比较繁忙的状态,占用率在60%-70%,已经是高负载,实际上linux内核从2.4开始就已经支持中断数在各个cpu上的负载均衡了,很显然我们没有充分利用已有的多cpu资源。

 

解决之道

     我们知道,任何外设(如磁盘,网卡等)需要cpu服务时,都会抛出一个中断,中断告诉cpu发生了什么事情,cpu就要停止目前的工作来处理这个中断。比如当网卡收到包时,假如cpu正在执行某个应用进程处理程序,此刻就会被网卡中断所打断执行中断处理程序。每个外设对应的中断处理程序自然是不同的,因此为了进行区分,防止多个设备发出相同的中断请求,系统中的每个设备都被分配了一个独一无二的IRQ(Interupt Request)

每个设备对应的IRQ信息可以从/proc/interrupts中读取:

第一列即为每台设备对应的IRQ,这个在不同机器上可能会不同,该图中我们可以看出网卡eth1对应的IRQ16

第二列到第五列分别对应cpu0-cpu3已经处理的关于某个IRQ(对应某设备)的中断数量。这是我做过优化之后的截图,可以看到各个cpu都处理了大概一样多的eth1网卡中断。

第六列对应中断控制器。

第七列就是具体的设备了。

其实我们的优化方法也就是想把eth1的中断请求平均分配在各个cpu上,从linux 2.4开始就实现了把IRQ绑定在某个cpu或者某些cpu上,叫做多cpu中断亲和性。要实现这一点,有若干条件:

1. eth1对应的中断控制器必须是IO-APIC芯片,有时候是硬件上支持,但IO-APIC未被启用,需要调整系统启动参数来更改,这一点一定要注意。

2. 只有特定CPU才支持,如果是那种CPU超线程的,没有办法,目前我实验过的一些INTEL至强处理器是支持的,如Intel(R) Xeon(R) CPU            5130  @ 2.00GHz,AMD的试过几个型号不支持。

设置中断分配的方法很简单,就是修改/proc/irq/IRQ/smp_affinity,这里IRQ前面已经说过可以从/proc/interrupts里面查,上图的例子中eth1对应的IRQ16,如果我们需要把eth1网卡中断被各个cpu平均处理,只需要执行如下命令:

echo ff > /proc/irq/16/ smp_affinity

     如果想把eth1对应的中断绑定在cpu2上处理,执行:

      echo 04 > /proc/irq/16/ smp_affinity

  此处echo的数字为十六进制,置1的位对应cpu生效,1对应cpu0, 2对应cpu1, 4对应cpu28对应cpu3,如此类推。

     下面看下我们优化后的效果吧:

       可以看出cpu繁忙程度平均了,单个cpu的占用率只有20-30%了,处理能力大大提升。

   上面截图都是在聊天记录漫游的几台机器上做的优化,优化后机器cpu负载大大降低,不需要进行扩容,有效降低了运营成本。

 

附:

1、如何察看某个进程在哪个CPU上运行:

#top

之后按下f 进入top Current Fields设置页面:

选中:j: P          = Last used cpu (SMP)

则多了一项:P 显示此进程使用哪个CPU。

2、Linux下,如何看每个CPU的使用率:

#top

之后按下1. 则显示多个CPU

Cpu0  :  1.0%us,  3.0%sy,  0.0%ni, 96.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu1  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st

另外,shift+p,按cpu使用率排序,shift+m,按内存使用率排序

 

 

你可能感兴趣的:(linux)