云主机tap口丢包问题

背景

某一用户在云平台上,在同一个VPC建立3台云主机,2台centos6.3(16vcpu,8G内存)和一台windows2008 sever(4 vcpu,4G内存)云主机;

我们编号为A,B,C ,其中A代表压力客户端云主机, B代表应用后台服务器云主机, C代表存储服务器云主机

通过A持续压力B,发现网络流量只有50Mb情况下,在外部ping服务器B出现大幅动的延迟波动,在15ms以上,有时候甚至50ms;而无压力情况下ping 浮动ip延迟在5ms以下;

且此时查看云主机接口发现连接云主机B的tap口丢包很严重,约丢1000个左右。

cc.png

困惑

为什么tap口有丢包计数,使用tcpdump抓取tap口的数据包和云主机内部的icmp数据包,而云主机内部没有收到该数据包,所以云主机明明抓取到该数据包

为什么会有丢包计数?为什么云主机内部收不到?且云主机内部接口没有丢包计数

答案

这也是后续分析linux源码找到的答案,tcpdump 抓取tap口数据包在计数统计之前,所以tcpdump在tap口抓取到该数据包并不代表该数据包已经发到云主机内部了,所以

可以推断,该tap丢包问题,应该是云主机处理数据包较慢,无法及时取出tap送给的数据包,导致tap发送数据包的队列满了,丢弃了后面后面收到的数据包;

性能问题易疏导不易调大,所以重点是为什么云主机处理数据包慢?当然这些都是后续解决该问题过程中逐渐形成的认知,写在此处以回答最初的疑惑

问题分析阶段1

上述问题是用户在使用云主机发现的性能问题,在高压力情况下才出现,问题点在于压力情况下的云主机网络处理的稳定性和丢包问题;在处理该问题时候我还是一个云计算的刚刚入门不到5个月的小白,对虚拟机网络调优还接触不多。

于是从流量角度对该问题进行分析复现,通过分析问题现场抓取的数据包可以知道,该应用属于小包应用,每秒大概单向7w个数据包,所以自然而然通过pps测试来进行问题的复现,当时就借用了阿里pps测试用例对云主机的pps情况进行测试

工作 https://www.alibabacloud.com/help/zh/faq-detail/55757.htm

测试结果如下:

流测试后,约5分钟pps在25w左右波动,且有0.5%左右丢包率

5分钟后丢包服务的丢包率为0,pps稳定在13.5w,一直维持到20分钟测试结束

测试过程中ping server1 和server2未出现丢包

问题分析阶段2

性能优化前:收包PPS(Packet per Second)约25-30万;发包PPS约为12万

性能优化后:收包PPS(Packet per Second)约50-55万,丢包率约0.73%;发包PPS约为40万

包大小和协议:UDP包,大小约64Bytes

虚拟机环境(Server):16vCore/16G

测试工具:iperf3

虚机操作系统:Centos 7.3

阿里云同等规格(16vCore/16G)云主机:

不同测试场景结果差异较大,

8台陪练机,一台测试机场景下,收包pps为40wpps左右,丢包较严重,平均丢包率36%

将陪练机减少至3台时性能表现最好,收包pps为可达到规格介绍中60wpps,丢包率约2.3%

做的优化操作如下

网络方向:

  1. 开启虚拟网卡软件层面的RPS和RFS

  2. 开启虚拟网卡硬件层面的多队列(RSS)

CPU资源方向:

  1. 宿主机 QEMU和CPU 做亲和处理

  2. 调整虚机网卡中断和CPU关联关系,优化中断处理

问题分析阶段3

经过上述的pps测试后,虽然能够提升pps能力,但是也随之发现一个带宽的问题,经过对云主机的测试发现,通过TCP进行带宽测试,每次测试持续5分钟

测试命令和步骤如下

一个客户端,一个服务器端 服务器端启动netperf服务器端进程 客户端启动netperf客户端进程

测试命令如下:

netperf -H serverip -t TCP_STREAM -l 300 – -m 1440

测试结果:

发现云主机的带宽在5000Mb/s-6000Mb每秒

测试结果分析:

通过对比友商的云主机性能,单连接带宽测试维持在8000Mb/s 以上,且波动较少,所以得知,虽然当时云主机可以通过多条连接进行带宽测试,也能将带宽打到8000Mb以上,但是单条连接和多条连接

是不一样的,单条连接更能说明当前云主机的带宽还需要调优。

问题分析阶段4

思路

抓住单带宽上不去的问题,对云主机和云主机所在HOST主机进行调优工作,所做的尝试核心指导思想如下

关闭irqbalance
设置计算节点CPU处于高性能模式 虚拟机使用VCPU和nova、neutron等服务使用VCPU分离 限定云主机进程尽量在同一个NUMA node中
云主机内调优:
开启RPS(Receive Package Steering)和RFS(Receive Flow Steering)

总结:该阶段所作的努力是为了减少波动性,关闭HOST主机的irqbalance想法是,云主机的qume进程不会因为该程序的调度而频繁出现缓存丢失情况,导致性能降低

让英特尔CPU处于高性能模式,属于踩的不小的坑才做的发现的调优参数,因为HOST主机CPU如果处于power save模式,会使得云主机出现休眠会间接导致很多问题,且CPU也没有发挥性能优势,导致性能下降

然后就是HOST主机侧也会有处云主机外的其它辅助、云存储进程等,这些进程也会和云主机qume进程争抢CPU,导致互相影响,导致云主机的性能降低

限定云主机进程尽量在同一个NUMA node中,云主机在同一个NUMA node命中L2 L3缓存的概率大大增加,减少了跨NUMA访问带来的高延迟内存访问,提升云主机访存时间提升性能

当时采用的centos7作为调优的云主机系统,采用单队列,虽然云主机的CPU很多,但是所有的网络流量中断只触发CPU 0 ,导致cpu0的si特别高,而且会出现收包忙不过来的情况,所以在单队列情况下,云主机哪部就开启了RPS

开启RPS后,CPU0其实仍主要被中断触发,但是其软中断时间就短了,cpu0只需要将数据包根据hash挂到其它cpu所处理的队列中,触发个信号告诉其它CPU处理即可,其它CPU就把该数据包触发软中断,消耗该数据包。这样就会cpu0减轻了很大的负担,他就能处理更多的网络流量了

开启RFS,和RFS配合使用在哪个CPU收包,就使用哪个CPU处理上层应用程序,这样可以减少缓存的miss,提升性能

taskset绑定应用程序,这个其实属于更细粒度的调优方法了,让应用程序固定在某一个CPU,减少缓存miss,当然绑定CPU应该尽量的空闲,保证出现低争抢,效果会更好。

上述算是调整思想的一个汇总,其实还有一部分没有提到就是云主机CPU绑定方法,所有的做法其实和CPU绑定出于同源,CPU绑定好了,再稍稍调整下参数,单TCP带宽问题不大

CPU绑定方法

virsh emulatorpin instance-000000a8 5 –live

virsh vcpupin instance-000000a8 0 6 –live

virsh vcpupin instance-000000a8 1 7 –live

将和云主机中断模拟的线程交给vcpu5处理,将云主机的cpu交给无力cpu6和7号处理

结果

经过上述操作,带带宽稳定在8000Mb以上,达到调优目标了

问题分析阶段5

经过上述折腾后,于是和用户申请现网测试环境,开始调试工作,主要做的动作如下

云主机内开启RPS和RFS

1
2
3
4
5
6
7
echo ff > /sys/class/net/eth0/queues/rx-0/rps_cpus
echo 4096 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt
echo 4096 > /proc/sys/net/core/rps_sock_flow_entries

echo 0 > /sys/class/net/eth0/queues/rx-0/rps_cpus
echo 0 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt
echo 0 > /proc/sys/net/core/rps_sock_flow_entries

host主机隔离以及绑定

做如下操作:

1,分离部分跑的较高的进程到0,2,4,6 vcpu,

2,将云主机进程binding到8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38

taskset -cp 0,2,4,6 939

taskset -cp 0,2,4,6 195385

taskset -cp 0,2,4,6 117891

taskset -cp 0,2,4,6 4575

taskset -cp 0,2,4,6 117972

taskset -cp 0,2,4,6 195374

查看是否生效

taskset -cp 939

taskset -cp 195385

taskset -cp 117891

taskset -cp 4575

taskset -cp 117972

taskset -cp 195374

virsh emulatorpin instance-0000025f 8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38

查看是否生效

takset -cp 55428

经过调整后,用户进行应用测试,发现延迟波动很小,虽tap有小部分丢包,但是ping fip没有出现丢包了,满足了用户的需求

问题分析阶段6

虽然知道怎么调整了,可是怎么样形成可以实施的方案?

且还有一点没有考虑清楚,其实云主机的进程有两种,一种是模拟中断处理网络的线程;一种是云主机工作vcpu;前面主要是针对于模拟中断处理网络的线程做绑定操作,而对云主机工作vcpu并没有进行绑定动作

于是vcpupin也需要运用到方案

解析

方案1

将HOST物理主机CPU使用率超过2%的进程固定到0-3CPU处理,将云主机enulator pin 到4-7,vcpu pin 到后剩余的CPU

方案2

将HOST物理主机CPU使用率超过2%的进程固定到0-3CPU处理,将云主机enulator pin 到4-7,vcpu pin同一个NUMA

方案3

isocpus/nohzfull/rcunocbs隔离出CPU5-31,将云主机enulator pin 到4-7,一对一vcpu pin同一个NUMA物理vpcu

于是对上述的方案进行验证工作,发现效果,方案1 > 方案2 > 方案3

但是方案3需要重启,对于已经上线的云平台来说,重启物理主机会带来较大的风险,想比较方案2比方案1稍稍麻烦一些,于是方案1 是最佳选择

问题总结

经过上述过程,该tap丢包问题定位,到最终的解决方案算是完成了,具体的技术细节就不在此文描述了,你可以自己goole,当然后续文章会对整个收报流程进行分析

并结合当前问题定位过程,进行一轮理论与 实践的结合分析,目的是将整个数据包从物理网卡到云主机应用程序之间到底经过了什么步骤表达清楚,后续再此遇到丢包等问题时候

可以快速的定位问题,和给出问题的可能性,举一反三。