说说网卡中断处理

多数Java程序员很少会接触到这块,但对于经常做分布式Java应用的同学来说,还是一个基本技能,毕竟到了如今多核时代,如果仅仅因为网卡中断处理不均衡导致系统吞吐量上不去的话有点不划算,不过其实我也不怎么懂,毕竟这个涉及硬件、驱动等方面的知识,就讲个大概吧,欢迎大家指正错误。

有些Java应用在压力大的时候,会看到有一个cpu的hi和si明显比其他的高,有可能其他cpu util并不高,如果只是因为这个导致应用的吞吐量上不去,显然太不划算了,如果这是一个远程交互比较多的应用,那么八成是网卡中断处理不均衡的问题,为什么会有这样的问题呢,简单说说背景以及目前可用的解决这个瓶颈的方法。

网卡收到一定的数据后,驱动会产生中断,然后交由CPU来处理,在单核时代,直接扔给那个核处理就OK,但多核时代呢,怎么办呢,一种最简单的能想到的方法自然是RR,就第一个给cpu 0,第二个给cpu 1,但这会导致包乱序的问题,没办法采用。

为了能充分发挥多核的能力,google的Tom Herbert做了个patch,称为Receive Packet Steering,缩写为RPS,能够做到将网卡中断较为均衡的分散到多个CPU,简单来说,是网卡驱动对每个流生成一个hash标识,然后由中断处理的地方根据这个hash标识分配到相应的CPU上去,这样就可以比较充分的发挥多核的能力了。

随着RPS的投入使用,又发现上面的改进可能会碰到一个问题,就是应用处理的cpu和数据流的cpu不在同一个上,这会导致cpu cache miss比较严重,因此Tom继续做了个改进版,称为Receive flow steering,缩写为RFS。

目前RPS和RFS已集成到linux 2.6.35中,如果是这个版本的以上的可以直接使用,如果是低于这个版本的,就只能自己backport了,但据一些玩内核的同学的经验,这个patch还不是很好backport…

上面的这种是比较乞丐版的让网卡中断能够均衡的方法,而更“高富帅”一点的做法是采用支持多队列的网卡,要使用上多队列网卡,一个前提是linux内核必须>=2.6.21,可通过lspci -vvv | grep -i msi-x来查看网卡是不是支持多队列的,后面会有一个enable、count/tabsize之类的参数,有些网卡是支持的,但驱动默认没打开,这种可以查看一些user guide去打开。

在网卡多队列开启的情况下,可以通过cat /proc/interrupts来看看eth的那些,通常会看到eth0-TxRx-0等,这表明是打开了的,网卡的多队列个数是固定的,因此可能会出现网卡的队列个数和cpu核数不对应的现象,网卡驱动在初始化的时候会根据cpu core数来决定绑定(有些网卡驱动不一定是这样,所以最好确认下),也可以自己手工修改/proc/irq/[中断号]/smp_affinity来绑定。

可以看到,在网卡多队列能开启的情况下,通常网卡中断的处理是会比较均衡的,但会缺少RFS那个中断处理cpu和应用处理的cpu是同一个的改进,所以即使是网卡多队列的,在内核支持的情况下,也可以开启RFS看看。

参考资料:
Receive packet steering
Receive flow steering
http://blog.csdn.net/h_flight/article/details/9121999
http://blog.csdn.net/wyaibyn/article/details/14109325

=============================
欢迎关注微信公众号:hellojavacases

关于此微信号:
分享Java问题排查的Case、Java业界的动态和新技术、Java的一些小知识点Test,以及和大家一起讨论一些Java问题或场景,这里只有Java细节的分享,没有大道理、大架构和大框架。

公众号上发布的消息都存放在http://hellojava.info上。

《说说网卡中断处理》有4个想法

  1. 额,没太看懂。在gecko那个开源框架中,初始化线程池大小时,有这样一个一个方法:

    /**
    * 默认为CPU个数-1,留一个CPU做网卡中断
    *
    * @return
    */
    public static int getSystemThreadCount() {
    final int cpus = getCpuProcessorCount();
    final int result = cpus – 1;
    return result == 0 ? 1 : result;
    }

    为啥要单独留一个cpu处理网卡中断呢?

    1. @zhangyou1010
      这个真心不知道,但说实话,nio框架这个我觉得在java领域基本都不需要选择,就用netty吧,其他的开源框架的可持续性发展能力是完全不能和netty相比的。

发表评论

电子邮件地址不会被公开。 必填项已用*标注


*