一、前缀知识点
1、CPU工作机制:系统采用中断机制协同处理CPU与其他设备工作
2、网卡和CPU:长久以来网卡的中断默认由cpu0处理,在大量小包的网络环境下可能出现cpu0负载高,而其他cpu空闲的情况。
硬件网卡多队列:
3、MSI-X:MSI-X是一种比MSI更合理的中断机制,它能扩展PCIe设备使用中断向量的个数,同时解决MSI中断机制要求使用中断向量号连续所带来的问题。MSI中断机制最多只能使用32个中断向量,而MSI-X可以使用更多的中断向量。
4、网卡和MSI-X:网卡使用MSI-X产生多个中断并分配到不同CPU,降低单个CPU的压力,提高网络性能
5、SMP IRQ affinity:Linux 2.4内核之后引入了将特定中断绑定到指定的CPU的技术。
6、网卡和SMP IRQ affinity:如果网卡有多队列,就会有多个中断号,这样就可以把不同的中断号分配到不同CPU上,这样中断号就能相对均匀的分配到不同的CPU上。但是对于单队列的网卡配置SMP IRQ affinity对多CPU无效。
6、RSS:网卡的硬件特性,实现了多队列,可以将不同的流分发到不同的CPU上。
7、网卡的多个中断号和RSS:通过将中断号绑定到多CPU并没有真正实现中断的分配。支持RSS的网卡,通过多队列技术,每个队列对应一个中断号,通过对每个中断的绑定,可以实现网卡中断在cpu多核上的分配。原本是CPU-中断交互,现在则是CPU-RSS队列-中断交互。
7、CPU和RSS:默认情况下,每个cpu核对应一个RSS队列。ixgbe驱动将收到的数据包的源、目的ip地址和端口号,交由网卡硬件计算出一个rss hash值,再根据这个hash值来决定将数据包分配到哪个队列中,即将将一条流放到同一个队列上。通过cat /proc/interrupts |grep 网卡名的方式,就可以看到网卡使用了几个rss通道。
软件网卡多队列:
8、RPS:RPS(Receive Packet Steering)主要是把软中断的负载均衡到各个cpu,简单来说,是网卡驱动对每个流生成一个hash标识,这个HASH值得计算可以通过四元组来计算(SIP,SPORT,DIP,DPORT),然后由中断处理的地方根据这个hash标识分配到相应的CPU上去,将一条流放到同一个队列上,这样就可以比较充分的发挥多核的能力了。通俗点来说就是在软件层面模拟实现硬件的多队列网卡功能,如果网卡本身支持多队列功能的话RPS就不会有任何的作用。该功能主要针对单队列网卡多CPU环境,如网卡支持多队列则可使用SMP irq affinity直接绑定硬中断。
图:只使用RPS的情况
9、RFS:由于RPS只是单纯把数据包均衡到不同的cpu,这个时候如果应用程序所在的cpu和软中断处理的cpu不是同一个,此时对于cpu cache的影响会很大,那么RFS(Receive flow steering)确保应用程序处理的cpu跟软中断处理的cpu是同一个,这样就充分利用cpu的cache,这两个补丁往往都是一起设置,来达到最好的优化效果, 主要是针对单队列网卡多CPU环境。
图:使用RFS后
10、RPS和RFS:RFS依靠RPS的机制插入数据包到指定CPU的backlog队列,并唤醒那个CPU来执行
二、netmap性能优化
由于过多的网卡收包和发包中断集中在一个CPU上,在系统繁忙时,CPU对网卡的中断无法响应,这样导致了服务器端的网络性能降低,从这里可以看出其实网络性能的瓶颈不在于网卡,而是CPU。所以我们使用网卡多队列技术提高CPU的使用性能。
1、软件级多队列:RPS+RFS,使用netmap从所有或指定队列读取数据
2、硬件级多队列:支持多队列(MSI-X多中断号)的网卡+RSS+IRQ中断绑定,使用netmap从所有或指定队列读取数据
3、非多队列方案:lb是一款基于netmap的应用,在netmap源码的app目录下。他可以根据参数生成指定的pipe(管道),然后从指定port读取流量,将流量hash(源IP,目的IP,源端口,目的端口)到不同管道。使用lb可以达到网卡多队列类似的效果,此时则可以使用netmap对所有或者指定管道进行读取。(使用的时候请看一遍lb的指令说明和netmap基本使用,避免落入坑中,比如开启了lb之后网络会断掉是因为lb内部使用netmap抓了所有包而没把网络通信的包放回主机栈,处理这个问题需要将管理流量送回到主机协议栈,并且将主机协议栈的响应发回给网卡。最简单的方法是修改lb,将符合我们分析要求发送到pipe,不符合我们分析要求的直接与主机协议栈交互)
建议:
1、以上方案还可以使用CPU affinity将每一个netmap的进程绑定到不同CPU以提高进一步的性能
2、若是进行流量分析,建议使用双网卡。一张网卡进行日常活动的流量管理,另一张网卡专供netmap使用,这样的话,将分析流量全部指向netmap分析用的网卡,使用netmap也不会导致网络瘫痪。
CPU affinity:进程要在某个给定的 CPU 上尽量长时间地运行而不被迁移到其他处理器的倾向性。Linux 内核进程调度器天生就具有被称为 软 CPU 亲和性(affinity) 的特性,这意味着进程通常不会在处理器之间频繁迁移。这种状态正是我们希望的,因为进程迁移的频率小就意味着产生的负载小。
2.6 版本的 Linux 内核还包含了一种机制,它让开发人员可以编程实现 硬 CPU 亲和性(affinity)。这意味着应用程序可以显式地指定进程在哪个(或哪些)处理器上运行。
三、参考资料