操作场景
随着网络IO的带宽不断提升,单核CPU处理网络中断存在瓶颈,不能完全满足网卡的需求,通过开启网卡多队列功能,您可以将弹性云主机中的网卡中断分散给不同的CPU处理,以满足网卡的需求,从而提升网络PPS和带宽性能。
网卡多队列支持列表
网卡多队列的支持情况和实例规格、虚拟化类型、镜像的操作系统有关,只有同时满足这些要求,云主机才能开启网卡多队列功能。
- 支持网卡多队列的实例规格请参见《弹性云主机用户指南》的“产品介绍 > 实例 > 实例规格 > 规格清单”章节。
说明:
- 网卡多队列数为大于1的值,表示支持网卡多队列。
- 虚拟化类型必须为KVM,XEN类型不支持网卡多队列。
- Linux云主机网卡多队列支持列表所列的Linux公共镜像,支持网卡多队列。
说明:
- Windows操作系统暂未商用支持网卡多队列,如果对Windows操作系统镜像开启网卡多队列功能,可能会引起操作系统启动速度变慢等问题。
- Linux操作系统弹性云主机建议将操作系统内核版本升级至2.6.35及以上,否则不支持网卡多队列。
- 建议您使用命令uname -r查询内核版本,如果低于2.6.35请联系技术支持升级内核。
Windows云主机网卡多队列支持列表
类别 | 镜像 | 是否支持多队列 |
---|---|---|
Windows | Windows Server 2008 WEB R2 64bit | 可通过私有镜像支持 |
Windows Server 2008 Enterprise SP2 64bit | 可通过私有镜像支持 | |
Windows Server 2008 R2 Standard/Datacenter/Enterprise 64bit | 可通过私有镜像支持 | |
Windows Server 2008 R2 Enterprise 64bit_WithGPUdriver | 可通过私有镜像支持 | |
Windows Server 2012 R2 Standard 64bit_WithGPUdriver | 可通过私有镜像支持 | |
Windows Server 2012 R2 Standard/Datacenter 64bit | 可通过私有镜像支持 |
表Linux云主机网卡多队列支持列表
类别 | 镜像 | 是否支持多队列 | 是否默认开启多队列 |
---|---|---|---|
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 | 是 | 是 |
操作说明
假设以下场景所述的云主机满足规格和虚拟化类型要求:
- 使用网卡多队列支持列表中的公共镜像创建的云主机,默认已开启网卡多队列,无需执行本节操作。
- 对于私有镜像场景,如果您的外部镜像文件的操作系统在网卡多队列支持列表范围内,需要按照如下流程开启网卡多队列:
a. 将外部镜像文件导入镜像服务控制台。
b. 为镜像添加网卡多队列标签。
c. 使用私有镜像创建云主机。
d. 开启网卡多队列。
将外部镜像文件导入镜像服务控制台
将外部镜像文件导入镜像服务控制台,详细操作请参见注册镜像(Linux)。
为镜像添加网卡多队列标签
Windows操作系统暂未商用支持网卡多队列,如果对Windows操作系统镜像添加网卡多队列标签,开启网卡多队列功能,可能会引起操作系统启动速度变慢等问题。
用户可以选择以下任意一种方式设置镜像的网卡多队列属性。
方式1 :
- 登录控制台。
- 选择“ 镜像服务”。
进入镜像服务页面。
- 单击“私有镜像”页签,在对应镜像所在行的“操作”列下,单击“修改”。
- 设置镜像的网卡多队列属性。
方式2 :
- 登录控制台。
- 选择“镜像服务”。
进入镜像服务页面。
- 单击“私有镜像”页签,在镜像列表中,单击镜像名称,进入镜像详情页面。
- 单击右上角的“修改”,在弹出的“修改镜像”对话框中,设置镜像的网卡多队列属性。
使用私有镜像创建云主机
使用注册好的私有镜像创建云主机,详细操作请参见《弹性云主机用户指南》。在配置参数时,需要注意以下两点:
- 区域:必须选择私有镜像所在的区域。
- 镜像:选择“私有镜像”,并在下拉列表中选择需要的镜像。
开启网卡多队列
使用Windows操作系统的KVM弹性云主机,可通过私有镜像支持网卡多队列功能。
使用Linux操作系统的弹性云主机,本节以CentOS 7.4为例,介绍开启网卡多队列的具体操作:
步骤 1 开启网卡多队列功能
- 登录弹性云主机。
- 执行以下命令,查看网卡支持和已开启的队列数。
ethtool -l 网卡
- 执行以下命令,设置网卡当前使用的队列数。
ethtool -L 网卡 combined 队列数
示例:
[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个队列
步骤 2 (可选)建议开启irqbalance服务,让系统自动调整网卡中断在多个CPU核上的分配。
- 执行以下命令,开启irqbalance服务。
service irqbalance start
- 执行以下命令,查询irqbalance服务状态。
service irqbalance status
如果回显中“Active”字段的值包含“active (running)”,表示irqbalance服务已正常开启,如下图所示。
irqbalance服务正常开启
步骤 3 (可选)开启中断绑定。
开启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
步骤 4 (可选)开启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