开启网卡多队列功能
操作场景
随着网络IO的带宽不断提升,单核CPU处理网络中断存在瓶颈,不能完全满足网卡的需求,通过开启网卡多队列功能,您可以将弹性云服务器中的网卡中断分散给不同的CPU处理,以满足网卡的需求,从而提升网络PPS和带宽性能。
假设以下场景所述的弹性云服务器满足规格和虚拟化类型要求:
- 使用网卡多队列支持列表中的公共镜像创建的弹性云服务器,默认已开启网卡多队列,无需执行本节操作。
- 对于私有镜像场景,如果您的外部镜像文件的操作系统在网卡多队列支持列表范围内,需要按照如下流程开启网卡多队列:
网卡多队列支持列表
网卡多队列的支持情况和实例规格、虚拟化类型、镜像的操作系统有关,只有同时满足这些要求,弹性云服务器才能开启网卡多队列功能。
镜像 |
是否支持多队列 |
是否默认开启多队列 |
---|---|---|
Ubuntu 14.04/16.04/18.04/20.04 server 64bit |
是 |
是 |
OpenSUSE 42.2/15.* 64bit |
是 |
是 |
SUSE Enterprise 12 SP1/SP2 64bit |
是 |
是 |
CentOS 6.8/6.9/7.*/8.* 64bit |
是 |
是 |
Debian 8.0.0/8.8.0/8.9.0/9.0.0/10.0.0/10.2.0 64bit |
是 |
是 |
Fedora 24/25/30 64bit |
是 |
是 |
EulerOS 2.2/2.3/2.5 64bit |
是 |
是 |
类别 |
镜像 |
支持度 |
---|---|---|
Windows |
Windows Server 2008 WEB R2 64bit |
可通过私有镜像支持 |
Windows Server 2008 R2 Standard/Datacenter/Enterprise 64bit |
可通过私有镜像支持 |
|
Windows Server 2012 R2 Standard/Datacenter 64bit |
可通过私有镜像支持 |
|
Windows Server 2016 Standard/Datacenter 64bit |
可通过私有镜像支持 |
|
Linux |
Ubuntu 14.04/16.04 server 64bit |
支持 |
OpenSUSE 42.2 64bit |
支持 |
|
SUSE Enterprise 12 SP1/SP2 64bit |
支持 |
|
CentOS 6.8/6.9/7.0/7.1/7.2/7.3/7.4/7.5/7.6 64bit |
支持 |
|
Debian 8.0.0/8.8.0/8.9.0/9.0.0 64bit |
支持 |
|
Fedora 24/25 64bit |
支持 |
|
EulerOS 2.2 64bit |
支持 |
为镜像添加网卡多队列标签
Windows操作系统暂未商用支持网卡多队列,如果对Windows操作系统镜像添加网卡多队列标签,开启网卡多队列功能,可能会引起操作系统启动速度变慢等问题。
用户可以选择以下任一种方式设置镜像的网卡多队列属性。
- 登录管理控制台。
- 选择“计算 > 镜像服务”。
- 单击“私有镜像”页签,在对应镜像所在行的“操作”列下,单击“修改”。
- 设置镜像的网卡多队列属性。
- 登录管理控制台。
- 选择“计算 > 镜像服务”。
- 单击“私有镜像”页签,在镜像列表中,单击镜像名称,进入镜像详情页面。
- 单击右上角的“修改”,在弹出的“修改镜像”对话框中,设置镜像的网卡多队列属性。
方法3:通过API为镜像添加网卡多队列标签hw_vif_multiqueue_enabled
- 获取Token的方法请参考《镜像服务API参考》中的“如何调用API > 认证鉴权”。
- “更新镜像信息”的API使用方法请参考《镜像服务API参考》中的“更新镜像信息(OpenStack原生)”章节。
- 在请求消息头中增加“X-Auth-Token”。
“X-Auth-Token”的取值为步骤1中获取的Token。
- 在请求消息头中增加“Content-Type”。
“Content-Type”取值为application/openstack-images-v2.1-json-patch
请求的URI格式为:
PATCH /v2/images/{image_id}
请求的body体如下所示。[ { "op":"add", "path":"/hw_vif_multiqueue_enabled", "value": "true" } ]
支持网卡多队列修改样例如图1所示。
开启网卡多队列
使用Windows操作系统的KVM弹性云服务器,可通过私有镜像支持网卡多队列功能,具体操作请参见《镜像服务用户指南》的“如何设置镜像的网卡多队列属性”章节。
使用Linux操作系统的弹性云服务器,本节以CentOS 7.4为例,介绍开启网卡多队列的具体操作:
- 开启网卡多队列功能
示例:
[root@localhost ~]# ethtool -l eth0 #查询网卡eth0的队列数 Channel parameters for eth0: Pre-set maximums: RX: 0 TX: 0 Other: 0 Combined: 4 #表示此网卡最多支持设置开启4个队列 Current hardware settings: RX: 0 TX: 0 Other: 0 Combined: 1 #表示当前开启的是1个队列 [root@localhost ~]# ethtool -L eth0 combined 4 #设置eth0网卡开启4个队列
- (可选)建议开启irqbalance服务,让系统自动调整网卡中断在多个CPU核上的分配。
- 执行以下命令,开启irqbalance服务。
- 执行以下命令,查询irqbalance服务状态。
如果回显中“Active”字段的值包含“active(running)”,表示irqbalance服务已正常开启,如图2所示。
- (可选)开启中断绑定。
开启irqbalance服务让中断自由调度,网络性能提升。如果提升后的网络性能仍不满足您的预期,可以手动设置弹性云服务器操作系统的中断亲和性。
具体操作如下:
执行以下脚本,使得弹性云服务器中每个CPU服务一个多队列的中断请求,一对一的对应设置。即一个队列对应一个中断号,一个中断号绑定一个CPU,一一对应。
#!/bin/bash service irqbalance stop eth_dirs=$(ls -d /sys/class/net/eth*) if [ $? -ne 0 ];then echo "Failed to find eth* , sleep 30" >> $ecs_network_log sleep 30 eth_dirs=$(ls -d /sys/class/net/eth*) fi for eth in $eth_dirs do cur_eth=$(basename $eth) cpu_count=`cat /proc/cpuinfo| grep "processor"| wc -l` virtio_name=$(ls -l /sys/class/net/"$cur_eth"/device/driver/ | grep pci |awk {'print $9'}) affinity_cpu=0 virtio_input="$virtio_name""-input" irqs_in=$(grep "$virtio_input" /proc/interrupts | awk -F ":" '{print $1}') for irq in ${irqs_in[*]} do echo $((affinity_cpu%cpu_count)) > /proc/irq/"$irq"/smp_affinity_list affinity_cpu=$[affinity_cpu+2] done affinity_cpu=1 virtio_output="$virtio_name""-output" irqs_out=$(grep "$virtio_output" /proc/interrupts | awk -F ":" '{print $1}') for irq in ${irqs_out[*]} do echo $((affinity_cpu%cpu_count)) > /proc/irq/"$irq"/smp_affinity_list affinity_cpu=$[affinity_cpu+2] done done
- (可选)开启XPS、RPS特性。
xps主要是针对多队列的网卡发送时的优化,当发送一个数据包的时候,它会根据CPU来选择对应的队列。
#!/bin/bash # enable XPS feature cpu_count=$(grep -c processor /proc/cpuinfo) dec2hex(){ echo $(printf "%x" $1) } eth_dirs=$(ls -d /sys/class/net/eth*) if [ $? -ne 0 ];then echo "Failed to find eth* , sleep 30" >> $ecs_network_log sleep 30 eth_dirs=$(ls -d /sys/class/net/eth*) fi for eth in $eth_dirs do cpu_id=1 cur_eth=$(basename $eth) cur_q_num=$(ethtool -l $cur_eth | grep -iA5 current | grep -i combined | awk {'print $2'}) for((i=0;i<cur_q_num;i++)) do if [ $i -eq $cpu_count ];then cpu_id=1 fi xps_file="/sys/class/net/${cur_eth}/queues/tx-$i/xps_cpus" rps_file="/sys/class/net/${cur_eth}/queues/rx-$i/rps_cpus" cpuset=$(dec2hex "$cpu_id") echo $cpuset > $xps_file echo $cpuset > $rps_file let cpu_id=cpu_id*2 done done