RPS和RFS介绍

一、名词解释

  • RPS(Receive Packet Steering,接收数据包转向)
  • RFS(Receive flow steering,接收流转向)
  • RSS(receive side scaling,接收方缩放)

二、介绍

RPS/RFS 功能是在Linux- 2.6.35中有google的工程师提交的两个补丁,这两个补丁的出现主要是基于以下两点现实的考虑:

这两个补丁的出现,是由于服务器的CPU越来越强劲,可以到达十几核、几十核,而网卡硬件队列则才4个、8个,这种发展的不匹配造成了CPU负载的不均衡。
上面的提到的是多队列网卡的情况,在单队列网卡的情况下,RPS/RFS相当于在系统层用软件模拟了多队列的情况,以便达到CPU的均衡。
  出现RFS/RPS的原因主要是由于过多的网卡收包和发包中断集中在一个CPU上,在系统繁忙时,CPU对网卡的中断无法响应,这样导致了服务器端的网络性能降低,从这里可以看出其实网络性能的瓶颈不在于网卡,而是CPU,因为现在的网卡很多都是万兆并且多队列的,如果有过多的中断集中在一个CPU上,将导致该CPU无法处理,所以可以使用该方法将网卡的中断分散到各个CPU上

  RPS(Receive Packet Steering)主要是把软中断的负载均衡到各个cpu,简单来说,是网卡驱动对每个流生成一个hash标识,这个HASH值得计算可以通过四元组来计算(SIP,SPORT,DIP,DPORT),然后由中断处理的地方根据这个hash标识分配到相应的CPU上去,这样就可以比较充分的发挥多核的能力了。通俗点来说就是在软件层面模拟实现硬件的多队列网卡功能,如果网卡本身支持多队列功能的话RPS就不会有任何的作用。该功能主要针对单队列网卡多CPU环境,如网卡支持多队列则可使用SMP irq affinity直接绑定硬中断。

三、rps配置方法

配置如下参数即可启用rps/rfs功能:

echo ff > /sys/class/net/queues/rx-*/rps_cpus
echo 4096 > /sys/class/net/queues/rx-*/rps_flow_cnt

8核的机器为ff,具体计算方法是第一颗cpu是00000001,第二个cpu是00000010,第3个cpu是 00000100。设置为0表示不支持此功能。

rps_flow_cnt就是RFS,表示当前网络设备rps队列的流表数,需要设置为2的整数次幂,建议设置为4096。数值越大,同时所能处理的rps流越多。

 

四、流程对比

开启RPS/RFS后,网络数据接收流程对比:

 

 

 从流程中可以看出,相比传统的被中断cpu处理数据包变为中断cpu将数据存入backlog,等待rps实现的软中断自行分配到映射到的cpu处理,进而交付给报文所属app正在运行的cpu处理。

五、多队列介绍

  网卡多队列,顾名思义,也就是传统网卡的DMA队列有多个,网卡有基于多个DMA队列的分配机制。多队列网卡已经是当前高速率网卡的主流。

  默认情况下,每个网络接口都有一个流量队列,一次由一个CPU处理。由于SND(安全网络分发器,SecureXL和CoreXL调度程序)在处理流量队列的CPU上运行,因此用于加速的CPU数量不能超过处理流量的接口数量。多队列可让您为每个网络接口配置多个流量队列。这意味着可以使用多个CPU进行加速。

  多队列网卡是一种技术,最初是用来解决网络IO QoS (quality of service)问题的,后来随着网络IO的带宽的不断提升,单核CPU不能完全处满足网卡的需求,通过多队列网卡驱动的支持,将各个队列通过中断绑定到不同的核上,以满足网卡的需求。

常见的有Intel的82575、82576,Boardcom的57711等,下面以公司的服务器使用较多的Intel 82575网卡为例,分析一下多队列网卡的硬件的实现以及linux内核软件的支持。

六、RFS(Receive Flow Steering)

​   RFS是RPS的功能扩展,用来提高CPU缓存命中率,减少网络延迟。RPS仅根据队列长度转发数据包,而RFS使用RPS后端计算最合适的CPU,然后根据数据包的应用程序的位置来转发数据包。(同1个sockect的包,命中为同1个CPU进行处理)

​ 默认情况下禁用RFS。要启用RFS,必须编辑两个文件:

  • /proc/sys/net/core/rps_sock_flow_entries:指定并发活动连接的最大预期数量。对于中等服务器负载,建议使用32768。在实践中,所有输入的值都被四舍五入到最接近的2次方。
  • /sys/class/net/device/queues/rx-queue/rps_flow_cnt它的值为rps_sock_flow_entries的值除以接收队列的数量。例如,如果rps_flow_条目设置为32768,并且有16个配置的接收队列,则rps_flow_cnt应设置为2048。对于单队列设备,rps_flow_cnt的值与rps_sock_flow_条目的值相同。

​ 同1个sockect的包,命中为同1个CPU进行处理。如果单个应用数据量大于单个CPU可以处理的数据量,可以通过配置更大的帧大小,来减少中断次数,从而减少CPU的处理工作量。或者,考虑 NIC offload选项或更快的CPU。

posted @ 2022-09-13 16:11  轻轻的吻  阅读(2886)  评论(0编辑  收藏  举报