云服务器网络优化方案
操作场景
为了提高程序的运行的性能,可以通过把云服务器上运行的某个进程,指定在某个CPU上工作,实现CPU性能调优。
为了获取更高的执行效率,应该保证一个CPU把一个完整的发送或者接收过程处理完,避免CPU切换。最好一个业务进程/线程固定在一个CPU、固定一个网卡发送队列,中断也使用这个CPU。对于跨NUMA的云服务器,应该尽量在一个NUMA上完成网络IO动作,避免NUMA间切换。(可以执行lscpu查看CPU相关信息判断是否跨NUMA。)
本节操作以C7.xlarge.2、CentOS 7.4操作系统的云服务器为例,介绍网络优化的方案。
其中C7.xlarge.2实例的网卡有0、1两个队列,有CPU0、CPU1、CPU2、CPU3四颗CPU。
场景一:单位CPU获取的带宽(Gbps)或者吞吐量(Mpps)最大
- 保证一个业务进程或线程固定在一个CPU。
taskset -pc cpu_id pid
- cpu_id为希望绑定的CPU,取值范围为[0, CPU最大数-1]。
- pid为希望绑核的业务进程。
例如,本例中使用iperf3作为业务进程,把两个进程分别绑定到CPU2和CPU3:
- 执行如下命令,获取iperf3进程状态。
ps aux | grep iperf3 | grep -v grep
[root@localhost ~]# ps aux | grep iperf3 | grep -v grep root 3161 9.7 0.0 9712 896 pts/0 R 08:22 0:01 iperf3 -c 192.168.1.61 -p 10000 -t 10000 -i 0 root 3163 9.0 0.0 9712 892 pts/0 S 08:22 0:01 iperf3 -c 192.168.1.61 -p 10001 -t 10000 -i 0
- 执行以下命令,指定进程运行在CPU2和CPU3上。
taskset -pc 3 3163
[root@localhost ~]# taskset -pc 2 3161 pid 3161's current affinity list: 0-3 pid 3161's new affinity list: 2 [root@localhost ~]# taskset -pc 3 3163 pid 3163's current affinity list: 0-3 pid 3163's new affinity list: 3
如果恢复配置到原来的状态,可以使用如下命令(0-3为初始设置时返回的current affinity list):
[root@localhost ~]# taskset -pc 0-3 3161 pid 3161's current affinity list: 2 pid 3161's new affinity list: 0-3 [root@localhost ~]# taskset -pc 0-3 3163 pid 3163's current affinity list: 3 pid 3163's new affinity list: 0-3
- 保证一个CPU固定使用一个网卡队列。
本例中让CPU2使用eth0的0号队列,CPU3使用eth0的1号队列。
- 修改前执行如下命令,首先查询原来的配置,便于恢复:
cat /sys/class/net/eth0/queues/tx-0/xps_cpus
cat /sys/class/net/eth0/queues/tx-1/xps_cpus
[root@localhost ~]# cat /sys/class/net/eth0/queues/tx-0/xps_cpus 0 [root@localhost ~]# cat /sys/class/net/eth0/queues/tx-1/xps_cpus 0
xps_cpus里显示的是CPUbitmask的16进制显示,0、1、2、3四个CPU对应的值分别是1、2、4、8。
- 通过如下的命令让CPU2使用eth0的0号队列,CPU3使用eth0的1号队列。
echo 4 > /sys/class/net/eth0/queues/tx-0/xps_cpus
echo 8 > /sys/class/net/eth0/queues/tx-1/xps_cpus
如需恢复原来的配置,使用如下命令:
echo 0 > /sys/class/net/eth0/queues/tx-0/xps_cpus
echo 0 > /sys/class/net/eth0/queues/tx-1/xps_cpus
- 修改前执行如下命令,首先查询原来的配置,便于恢复:
- 保证一个网卡队列的中断固定在一个CPU。这个CPU和业务进程的CPU相同。
- 首先查询eth0对应的virtio设备的名字,如下查询结果为virtio0。
[root@localhost ~]# ls /sys/class/net/eth0/device/driver/ | grep virtio virtio0
- 然后查询virtio0网卡使用的中断的名字,如下查询结果为24、25、26、27、28。
[root@localhost ~]# cat /proc/interrupts | grep virtio0 24: 0 0 0 0 PCI-MSI-edge virtio0-config 25: 105 52766 114 38738 PCI-MSI-edge virtio0-input.0 26: 79 49480 593063 403097 PCI-MSI-edge virtio0-output.0 27: 55 3594 46 36720 PCI-MSI-edge virtio0-input.1 28: 27277 1262879 0 12099829 PCI-MSI-edge virtio0-output.1
- 编辑irqbalance配置文件。
[root@localhost ~]# vim /etc/sysconfig/irqbalance
- 修改最后一行IRQBALANCE_ARGS为如下,这样irqbalance服务不再调度这几个中断。
IRQBALANCE_ARGS=--banirq=24-28
- 重启irqbalance服务。
[root@localhost ~]# service irqbalance restart
- 修改中断所在CPU,例如设置25、26号中断到CPU2; 27、28号中断到CPU3。
[root@localhost ~]# echo 2 > /proc/irq/25/smp_affinity_list [root@localhost ~]# echo 2 > /proc/irq/26/smp_affinity_list [root@localhost ~]# echo 3 > /proc/irq/27/smp_affinity_list [root@localhost ~]# echo 3 > /proc/irq/28/smp_affinity_list
- 首先查询eth0对应的virtio设备的名字,如下查询结果为virtio0。
场景二:获取的带宽(Gbps)或者吞吐量(Mpps)最高
场景二仅提供优化方案,需要具备相关网络知识,且根据云服务器实际情况和业务场景综合考虑具体操作。
建议首先尝试使用最优效率配置,即场景一:单位CPU获取的带宽(Gbps)或者吞吐量(Mpps)最大的操作方法。确认是否可以满足性能要求。当场景一的方法不满足需求的情况下,推荐使用本场景的方法。
- 对于即收又发的业务,可以把接收和发送中断分别绑定一个CPU,例如把3的25、26、27、28分别绑定到CPU0、1、2、3。
- 对于接收繁忙的业务,可以打开RPS(Receive Packet Steering),让一个中断的软中断分散到多个CPU。
场景三:获取最优的不丢包TCP带宽
场景三仅提供优化方案,需要具备相关网络知识,且根据云服务器实际情况和业务场景综合考虑具体操作。
为了获取稳定的TCP不丢包带宽,推荐从小到大修改,设置一个满足业务带宽要求的发送socket缓冲区大小。业务带宽要求应该小于云服务器规格的带宽大小,否则请更换更大规格的实例。
例如推荐从64K缓冲区开始,尝试64K、128K...socket缓冲区大小。
socket缓冲区大小设置示例:
int opt = 64 * 1024; if (setsockopt(sk, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) < 0 || setsockopt(sk, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) < 0) { log_err("socket buffer size set failed."); close(sk); return -1; }
使用小的发送缓冲区大小,可以避免由于瞬时发送速率太高,超过flavor带宽限速而引起的丢包,从而获得更稳定的带宽。
- 对于iperf3程序,可以使用-w参数指定缓冲区大小。
- 对于4.9及以上内核版本,推荐把操作系统的TCP拥塞控制算法修改为BBR算法,这样可以在不修改socket缓冲区大小的情况下,获得一个稳定的TCP不丢包带宽。
BBR(Bottleneck Bandwidth and Round-trip propagation time)是一种拥塞控制算法,能够在传输最大带宽的同时保证最小的时延。Linux 4.9及以上内核版本自带了该算法,关于把操作系统内核协议栈拥塞控制算法修改为BBR的具体方法可以查询相关网站。