网卡调优RSS、RPS、RFS和XPS

1.RSS(Receive Side Scaling)

        RSS(Receive Side Scaling)也叫多队列接收,可以硬件级别实现使用多核处理接收网络数据。可用于缓解因单个CPU过载,导致的接收中断处理瓶颈,并减少网络延迟。

        可以通过/proc/interrupts确定网络接口卡是否支持RSS。也可以在加载网络驱动程序后,通过“ls  -1   /sys/devices/*/*/device_pci_address/msi_irq” 的输出来查看。(需要网卡硬件及驱动同时支持)

        默认情况下,RSS是启用的。RSS的队列数量通常在/sys/class/net/device/queues/rx queue/中配置,其中device是网络设备的名称(例如eth1),rx queue是相应接收队列的名称。

        在配置RSS时,RedHat建议将队列数量限制为每个物理CPU核心一个队列。启用RSS后,会根据每个CPU使用情况来分配数据的处理。也可以使用ethtool --show-rxfh-indir和--set-rxfh-indir参数来修改使用的权重。

        irqbalance守护进程可以与RSS一起使用,它将减少跨节点内存传输和缓存线跳转的可能性。如果开启了irqbalance和RSS,通过irqbalance将与网络设备相关的中断定向到适当的RSS队列,可以实现最低的延迟。

2.Receive-Side Scaling (RSS)

        RPS与RSS类似,用于将数据包定向到特定的CPU进行处理。RPS是在软件级别实现的,有助于避免单队列网卡成为网络流量的瓶颈。

        与RSS相比,RPS有几个优势:

                RPS由于是基于软件的,所有网卡都可以使用;

                在处理新协议时,更容易增加软件过滤器;

                RPS不增加网络设备的硬件中断率。注意:RPS它引入了处理器间的中断(软中断);

        RPS是在/sys/class/net/device/queues/rx-queue/rps_cpus文件中配置接收队列,其中device是网络设备的名称(如eth0),rx-queue是相应接收队列的名称(如rx-0)。

        rps_cpus文件默认值为0,也就是禁用RPS,这样CPU既会处理数据中断,也会处理数据包。

        要指定CPU处理接收队列的中断数据,需要将CPU索引位设置为1。如,要使用CPU 0、1、2和3处理中断,只需要将rps_cpus文件值设置为00001111或 f(十六进制值=1+2+4+8)。

        对于单队列的网络设备,可以通过将RPS配置为在同一内存域中使用CPU,来实现最佳性能。在非NUMA系统上,这意味着可以使用所有可用的CPU。如果网络中断率极高时,非处理网络中断的CPU,也可能会提高性能。

        对于多队列的网络设备,同时开启RPS和RSS通常是没有用处的。因为默认情况下,RSS会将CPU映射到每个接收队列。注意:如果硬件队列少于CPU,并且RPS被配置为在同一内存域中使用CPU,则RPS仍然是有用的。

        开启rps后softirq消耗仍不均衡:发现开启rps后,softirq不均衡的情况有缓解,但仍有较大差异。用perf分析高消耗cpu的ksoftirqd,发现有很大一部分cpu消耗在网卡驱动的清理流程中。rps只能减轻cpu处理网络协议的开销,对于网卡驱动上的开销无优化效果,对于这种情况可以设置rps_cup时排除本身cpu,进一步减轻其开销。

        RPS只作用于数据的接收,对于发送没有效果

3.RFS(Receive Flow Steering)

        RFS扩展了RPS,用提高CPU缓存命中率的方法,减少网络延迟。在RPS仅根据队列长度转发数据包的情况下,RFS使用RPS后端计算最合适的CPU,然后根据使用数据包的应用程序的位置转发数据包。这提高了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_条目的值相同。

        从单个发送器接收的数据不会发送到多个CPU。如果从单个发送器接收的数据量大于单个CPU可以处理的数据量,请配置更大的帧大小,以减少中断次数,从而减少CPU的处理工作量。或者,考虑 NIC offload选项或更快的CPU。

4.RFS加速

        增加硬件辅助来提高RFS的速度,从而实现PFS的加速。

        只有满足以下条件,加速RFS才可用:网卡支持加速RFS;启用ntuple筛选;

        一旦满足这些条件,就会根据传统的RFS配置自动推导CPU到队列的映射。也就是说,CPU到队列的映射是基于驱动程序为每个接收队列配置的IRQ亲和力推导出来的。

5.NIC OFFLOADS

        默认的以太网最大传输单元(MTU)是1500字节,这是通常可以传输的最大帧大小。这可能会导致系统资源未充分利用,例如,如果有3200字节的数据用于传输,这将意味着生成三个较小的数据包。有几个称为offloads的选项,允许相关协议栈传输比正常MTU大的数据包。可以创建最大允许64KiB的数据包,并提供发送(Tx)和接收(Rx)选项。当发送或接收大量数据时,这意味着每发送或接收64KiB数据,就要处理一个大数据包,而不是多个较小的数据包。这意味着生成的中断请求更少,用于拆分或组合流量的处理开销更少,传输机会更多,从而导致吞吐量的总体增加。

5.1.Offload类型

TCP Segmentation Offload (TSO)

        使用TCP协议发送大数据包。使用NIC处理段,然后将TCP、IP和数据链路层协议头添加到每个数据段。

UDP Fragmentation Offload (UFO)

        使用UDP协议发送大数据包。使用NIC将IP碎片处理为MTU大小的数据包,用于大型UDP数据报文。

Generic Segmentation Offload (GSO)

        使用TCP或UDP协议发送大数据包。如果NIC无法处理数据段/报文,GSO将绕过NIC硬件执行相同的操作。它通过尽可能晚地延迟分段来实现的。

Large Receive Offload (LRO)

        使用TCP协议。所有传入数据包在接收时,都会重新分段,从而减少系统必须处理的段数。它们可以在驱动程序中合并,也可以使用NIC合并。

        LRO的一个问题是:它倾向于对所有传入的数据包进行重新排序,通常会忽略标头和其他可能导致错误的信息的差异。当启用IP转发时,通常不可能使用LRO。LRO与IP转发相结合可能会导致校验和错误。注意:如果/proc/sys/net/ipv4/ip_forward设置为1,则启用转发。

Generic Receive Offload (GRO)

        使用TCP或UDP协议。在对数据包重新排序时,GRO比LRO更严格。例如,它检查每个数据包的MAC报头(必须匹配),只有有限数量的TCP或IP报头可以不同,并且TCP时间戳必须匹配。重新排序可以由NIC或GSO代码处理。

5.2.使用NIC Offloads

        Offload应该用于传输或接收大量数据的高速系统,并且有利于吞吐量而不是延迟。使用Offload大大增加了驱动程序队列的容量,所以延迟可能会成为一个问题

        这方面的一个例子,一个系统使用大数据包大小传输大量数据,但也运行许多交互式应用程序。由于交互式应用程序以一定的时间间隔发送小数据包,因此在处理前面较大的数据包时,这些数据包可能会“被困”在缓冲区中,从而造成不可接受的延迟,这是一个非常现实的风险。

        可以使用ethtool命令检查Offload设置,某些设备可能被列为固定设置,这意味着它们无法更改。

  • RPS( Receive Packet Steering)是在单个CPU将数据从Ring Buffer取出后,网卡驱动通过四元组(SIP,SPORT,DIP,DPORT)生成一个hash值,然后根据这个hash值,自动分配到对应的CPU上进行数据处理,从而实现多核数据处理的能力
  • 和RFS(Receive Flow Steering)
  • Accelerated Receive Flow Steering
  • XPS: Transmit Packet Steering

6.XPS(Transmit Packet Steering)

        XPS通过创建CPU到网卡发送队列的对应关系,来保证处理发送软中断请求的CPU和向外发送数据包的CPU是同一个CPU,用来保证发送数据包时候的局部性。

        对于发送队列到CPU的映射有两种选择:

1、使用CPU映射
        通过指定发送队列在某几个CPU上处理,通过减小分发的CPU范围来减少锁开销以及cache miss。最常见的就是1对1,和上面说到的接收软中断绑核类似,通过 /sys/class/net/<dev>/queues/tx-<n>/xps_cpus文件设置,同样是bitmaps方式。

2、接收队列映射方式
        基于接收队列的映射来选择CPU,也就是说让接收队列和发送队列在同一个CPU,或指定范围的几个CPU来处理。这种方式对于多线程一直收发包的系统效果比较明显,收发包队列处理在同一个CPU,不仅减少了对其他CPU的打断,同时提高应用处理效率,收完包后直接在同个CPU继续发包,从而减小CPU消耗,同时减小包的时延。可通过/sys/class/net/<dev>/queues/tx-<n>/xps_rxqs文件设置(不是所有网卡都支持)。
        XPS对于单发送队列网卡没有效果

7.单网卡调优:开启RPS和RFS(默认关闭)

  • 开启CPU性能模式:cpupower frequency-set -g performance
  • 使用脚本rps.sh开启RPS和RFS;
  • ethtool -G p1p1 [rx|tx] 4096,检查设置结果ethtool -g p1p1
  • sysctl -w net.core.netdev_budget=600
  • 查看网卡相应收发包情况;

#!/bin/bash
rps() {
  net_interface=`ip link show | grep "state UP" | awk '{print $2}' | egrep -v '^docker|^veth' | tr ":\n" " "`

  for em in ${net_interface[@]}
  do
      rq_count=`ls /sys/class/net/$em/queues/rx-* -d | wc -l`
      rps_flow_cnt_value=`expr 32768 / $rq_count`

      for ((i=0; i< $rq_count; i++))
      do
          echo $rps_flow_cnt_value > /sys/class/net/$em/queues/rx-$i/rps_flow_cnt
      done

      flag=0
      while [ -f /sys/class/net/$em/queues/rx-$flag/rps_cpus ]
      do
          echo `cat  /sys/class/net/$em/queues/rx-$flag/rps_cpus | sed 's/0/f/g' ` >  /sys/class/net/$em/queues/rx-$flag/rps_cpus
          flag=$(($flag+1))
      done
  done
  echo 32768 > /proc/sys/net/core/rps_sock_flow_entries
  sysctl -p
}

check_rps() {
  ni_list=`ip link show | grep "state UP" | awk '{print $2}' | egrep -v "^docker|^veth" | tr ":\n" " "`
  for n in $ni_list
  do
      rx_queues=`ls /sys/class/net/$n/queues/ | grep "rx-[0-9]"`
      for q in $rx_queues
      do
          rps_cpus=`cat /sys/class/net/$n/queues/$q/rps_cpus`
          rps_flow_cnt=`cat /sys/class/net/$n/queues/$q/rps_flow_cnt`

          echo "[$n]" $q "--> rps_cpus =" $rps_cpus ", rps_flow_cnt =" $rps_flow_cnt
      done
  done
  rps_sock_flow_entries=`cat /proc/sys/net/core/rps_sock_flow_entries`
  echo "rps_sock_flow_entries =" $rps_sock_flow_entries
}


rps
check_rps

8.多队列网卡

8.1.查看主网卡支持多队列的情况

        其中Pre-set maximums中的combined字段大于1时,表示网卡支持多队列。而Current harware settings中的conbined则表示当前设置的网卡队列数,如果队列数大于1,就是已经开启了网卡多队列。

[root@localhost ~]# ethtool -l eth0
    Channel parameters for eth0:
        Pre-set maximums:
        RX: 0
        TX: 0
        Other: 0
        Combined: 64
    Current hardware settings:
        RX: 0
        TX: 0
        Other: 0
        Combined: 32

8.2.设置网卡多队列

ethtool -L eth1 combined 16

        注意:设置的队列数的前提是网卡首先要支持多队列,且不能超过网卡支持的最大的队列数。当网卡驱动比较老旧的时候,也有可能会设置失败,建议将网卡驱动先升级至最新版本。

Redhat的RSS参考文档http://xn--rss-8u3e363r/

  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

酷咪哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值