高并发多队列网卡设置CPU亲和性项目记录

之前我转载过一篇smp-affinity的文章https://blog.csdn.net/yue530tomtom/article/details/76216503

实例

做ssl加速卡(高并发)测试又遇到相同的问题,多队列网卡软中断过高,记录备忘

场景:nginx模拟业务服务器,worker不绑定;网卡队列亲和性不设置
结果:那叫一塌糊涂,3w TPS 0号CPU就满了, 其中si多达60%,其余的cpu空闲,总体CPU才使用20%不到

调整场景:多网卡队列绑定CPU亲和性,nginx绕开绑定网卡队列亲和性的CPU
结果:TPS4.8w 网卡打满,没有出现cpu使用率过高的情况

调整服务器:更换万兆网卡模块
结果:测试ssl加速卡的极限值~balabala

修订:20180418新增
到此并未结束,发现双c的cpu快压满时,编号刚好是1/2处的几颗cpu idle%最先压满,其他还有将近20%左右
高并发多队列网卡设置CPU亲和性项目记录_第1张图片
接着调整,将8个网卡队列的4个绑定在编号最前两个,剩余的4个绑定在从1/2处编号最前两个(项目中是40,标号是0~39,那么绑定0、1、20、21)【注意这里是手工绑定的没有使用脚本进行绑定】
结果比全部绑定在前4颗CPU上要优,且没有出现靠前和1/2靠前的几颗cpu长时间被耗尽的情况,相同情况下性能提升
高并发多队列网卡设置CPU亲和性项目记录_第2张图片

调整过程

在此说下绑定网卡队列亲和性
方式有两种原理都一样:手工绑定或者写个脚本(省不少事特别是调优需要多次设置)
手工方式把下面脚本里堆积的命令拆出来就可以,下面看脚本设置亲和性(不具有通用性,只是个我做的项目例子)

1、查看使用网卡支持的队列

./bindCpu.sh
或者
./bindCpu.sh list
[root@localhost ~]# ./bindCpu.sh 

Dev:em1
/proc/irq/155/smp_affinity
|----15500000000,00000000,00000000,00000000,00000000,00000001
/proc/irq/156/smp_affinity
|----15600000000,00000000,00000000,00000000,00000000,00000002
/proc/irq/157/smp_affinity
|----15700000000,00000000,00000000,00000000,00000000,00000004
/proc/irq/158/smp_affinity
|----15800000000,00000000,00000000,00000000,00000000,00000008
/proc/irq/159/smp_affinity
|----15900000000,00000000,00000000,00000000,00000000,00000010

Dev:em2
/proc/irq/160/smp_affinity
|----16000000000,00000000,00000000,00000000,00000000,00000001
/proc/irq/161/smp_affinity
|----16100000000,00000000,00000000,00000000,00000000,00000002
/proc/irq/162/smp_affinity
|----16200000000,00000000,00000000,00000000,00000000,00000004
/proc/irq/163/smp_affinity
|----16300000000,00000000,00000000,00000000,00000000,00000008
/proc/irq/164/smp_affinity
|----16400000000,00000000,00000000,00000000,00000000,00000010

Dev:em3
/proc/irq/198/smp_affinity
|----19800000000,00000000,00000000,00000000,00000000,00000001
/proc/irq/199/smp_affinity
|----19900000000,00000000,00000000,00000000,00000000,00000002
/proc/irq/200/smp_affinity
|----20000000000,00000000,00000000,00000000,00000000,00000004
/proc/irq/201/smp_affinity
|----20100000000,00000000,00000000,00000000,00000000,00000008
/proc/irq/202/smp_affinity
|----20200000000,00000000,00000000,00000000,00000000,00000010

Dev:em4
/proc/irq/203/smp_affinity
|----20300000000,00000000,00000000,00000000,00000000,00000001
/proc/irq/204/smp_affinity
|----20400000000,00000000,00000000,00000000,00000000,00000002
/proc/irq/205/smp_affinity
|----20500000000,00000000,00000000,00000000,00000000,00000004
/proc/irq/206/smp_affinity
|----20600000000,00000000,00000000,00000000,00000000,00000008
/proc/irq/207/smp_affinity
|----20700000000,00000000,00000000,00000000,00000000,00000010

Dev:p6p1
/proc/irq/101/smp_affinity
|----10100000000,00000000,00000000,00000000,00000000,00000001
/proc/irq/103/smp_affinity
|----10300000000,00000000,00000000,00000000,00000000,00000002
/proc/irq/104/smp_affinity
|----10400000000,00000000,00000000,00000000,00000000,00000004
/proc/irq/105/smp_affinity
|----10500000000,00000000,00000000,00000000,00000000,00000008
/proc/irq/106/smp_affinity
|----10600000000,00000000,00000000,00000000,00000000,00000010
/proc/irq/107/smp_affinity
|----10700000000,00000000,00000000,00000000,00000000,00000020
/proc/irq/108/smp_affinity
|----10800000000,00000000,00000000,00000000,00000000,00000040
/proc/irq/109/smp_affinity
|----10900000000,00000000,00000000,00000000,00000000,00000080
/proc/irq/110/smp_affinity
|----11000000000,00000000,00000000,00000000,00000000,00000100

Dev:p6p2
/proc/irq/112/smp_affinity
|----11200000000,00000000,00000000,00000000,00000000,01000000
/proc/irq/114/smp_affinity
|----11400000000,00000000,00000000,00000000,00000000,01000000
/proc/irq/115/smp_affinity
|----11500000000,00000000,00000000,00000000,00000000,01000000
/proc/irq/116/smp_affinity
|----11600000000,00000000,00000000,00000000,00000000,02000000
/proc/irq/117/smp_affinity
|----11700000000,00000000,00000000,00000000,00000000,02000000
/proc/irq/118/smp_affinity
|----11800000000,00000000,00000000,00000000,00000000,04000000
/proc/irq/119/smp_affinity
|----11900000000,00000000,00000000,00000000,00000000,04000000
/proc/irq/120/smp_affinity
|----12000000000,00000000,00000000,00000000,00000000,08000000
/proc/irq/121/smp_affinity
|----12100000000,00000000,00000000,00000000,00000000,08000000

2、设置网卡队列亲和性,每个队列绑定一颗单独的cpu

./bindCpu.sh set

3、脚本

treeStr="|----"
usage(){
echo "./`basename $0` [set|list]"
echo 
echo "set:按队列数从0号CPU开始依次绑定"
echo "list:列出个网卡队列情况"
echo
exit
}
if [ "$1" != "" ]
then
    cmdtype=$1
else
    cmdtype="list"
fi
if [ "$cmdtype" != "set" -a "$cmdtype" != "list" ]
then
usage
fi

#扩展:比如需要将多个队列绑定在一个cpu上,
#入参是绑定的队列数:如3就是每个cpu上面绑定3个队列;若是列表,列表的个数表示预计使用的cpu数(也有可能少于设置的数据当队列数少于参数总和时)如 3 2 2 则表示cpu0绑定3个队列,cpu1绑定2个队列,cpu2绑定2个(和剩余的所有队列)
#实现:加一个参数,程序顺序计算绑定的cpu编号;或者一个参数列表,队列按列表顺序绑定cpu,若参数总和多于队列数则忽略多余的,若参数综合少于队列数,剩余的全绑定在最后一个


echo
#此处有坑,不同的系统可能会不一样,根据情况修改
#作用是找出网络设备
#此处ifconfig的结果格式为:p6p2: flags=4163  mtu 1500
#还遇到到过格式为:eth0      Link encap:Ethernet  HWaddr 90:B1:1C:35:5E:14 
for dev in `ifconfig |grep ": "|grep -v "lo" |awk -F':' '{print $1}'`
do
    cpuFlag=1
    echo "Dev:"$dev
    for devseq in `grep $dev /proc/interrupts |awk '{print $1}'|sed -e 's/://g'`
      do
      echo  "/proc/irq/${devseq}/smp_affinity"
    if [ "$cmdtype" = "set" ]
    then
      echo `printf %0x ${cpuFlag}` >/proc/irq/${devseq}/smp_affinity
    fi
    sleep 0.5
    echo -n $treeStr$devseq 
    cat /proc/irq/${devseq}/smp_affinity
    ((cpuFlag=cpuFlag*2))
  done
    echo 
done

^_^后面的调整发现脚本有心无力 还是直接手动绑定了,懒得改脚本,脚本就当是一种思路参考吧。把不同的需求写成不同的函数模块,根据入参调用。此项目做完我再完善该部分,立杆为证。

扩展

亲和性介绍

Linux调度程序同时提供软CPU亲和性和硬CPU亲和性机制。

  • 软亲和性:进程并不会在处理器之间频繁迁移。
  • 硬亲和性:进程需要在您指定的处理器上运行

虽然linux尽力通过一种软的亲和性试图使进程尽量在同一个处理器上运行,但它也允许用户强制指定进程无论如何都必须在指定的处理器上运行。

CPU亲和性的使用与机制详细可以参考下前辈的博文:https://blog.csdn.net/sdulibh/article/details/65630684

硬亲和性使用场景

  • 需要大量计算:常见的标志是应用程序要在多处理器的机器上花费大量的计算时间。
  • 需要保持高CPU缓存命中率:如果一个给定的进程迁移到其他地方去了,那么它就失去了利用 CPU 缓存的优势。实际上,如果正在使用的 CPU 需要为自己缓存一些特殊的数据,那么所有其他 CPU 都会使这些数据在自己的缓存中失效。因此,如果有多个线程都需要相同的数据,那么将这些线程绑定到一个特定的 CPU 上是非常有意义的,这样就确保它们可以访问相同的缓存数据(或者至少可以提高缓存的命中率)。否则,这些线程可能会在不同的 CPU 上执行,这样会频繁地使其他缓存项失效。

你可能感兴趣的:(调试与优化,性能测试,Linux,shell,备忘)