弹性云服务器 ECS弹性云服务器 ECS

更新时间:2021/07/27 GMT+08:00
分享

云服务器网络优化方案

操作场景

为了提高程序的运行的性能,可以通过把云服务器上运行的某个进程,指定在某个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)最大

  1. 保证一个业务进程或线程固定在一个CPU。

    可以通过如下命令把某个进程绑定在特定CPU:

    tasket -pc cpu_id pid

    • cpu_id为希望绑定的CPU,取值范围为[0, CPU最大数-1]。
    • pid为希望绑核的业务进程。

    例如,本例中使用iperf3作为业务进程,把两个进程分别绑定到CPU2和CPU3:

    1. 执行如下命令,获取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
    2. 执行以下命令,指定进程运行在CPU2和CPU3上。

      taskset -pc 2 3161

      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
  2. 保证一个CPU固定使用一个网卡队列。

    本例中让CPU2使用eth0的0号队列,CPU3使用eth0的1号队列。

    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。

    2. 通过如下的命令让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

  3. 保证一个网卡队列的中断固定在一个CPU。这个CPU和业务进程的CPU相同。
    1. 首先查询eth0对应的virtio设备的名字,如下查询结果为virtio0。
        [root@localhost ~]# ls /sys/class/net/eth0/device/driver/ | grep virtio
        virtio0
    2. 然后查询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
    3. 编辑irqbalance配置文件。
       [root@localhost ~]# vim /etc/sysconfig/irqbalance
    4. 修改最后一行IRQBALANCE_ARGS为如下,这样irqbalance服务不再调度这几个中断。
       IRQBALANCE_ARGS=--banirq=24-28
    5. 重启irqbalance服务。
       [root@localhost ~]# service irqbalance restart
    6. 修改中断所在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

场景二:获取的带宽(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的具体方法可以查询相关网站。

分享:

其他 所有常见问题

more