网络丢包,其实是软中断过高!
我们的一个业务数据中转服务器,构建在内部私有云平台上,在数据传输高峰期,网络经常出现丢包现象。
起初以为是服务器出口带宽跑满导致的,查看监控,发现千兆网卡才跑了600M左右,带宽并未跑满,看起来是服务器内部有问题,于是登录服务器先查看下系统运行状态,执行top命令,截图如下:
![efe4851f45d8a784ddf98bca876a84da.png](https://i-blog.csdnimg.cn/blog_migrate/42d4269fd74d8e50976bbc7f1f95a98f.jpeg)
从图中可以看出,服务器配置为4核10G内存,系统整体负载并不高。但是在CPU输出一行,发现si输出高达37.5%,这个si表示软中断占用CPU的百分比,软中断这么高,接下来就看看系统的中断情况。
//
查看系统中断情况
//
要查看中断分布情况,即CPU都在哪些设备上干活,干了多少,最简单方法如下:
![75eebddbc1169a803397e0953c904466.png](https://i-blog.csdnimg.cn/blog_migrate/8468aa097d17e18b5e0af0cae1781686.jpeg)
这个输出记录的是自系统启动以来,每个CPU处理各类中断的数量(第一列是中断号(IRQ),最后一列是对应的设备名),从上面可以看到:eth0所出发的中断几乎全部都是CPU2在处理,而CPU0、CPU1、CPU3所处理的中断请求非常少,甚至没有。
要查看中断状态,也可以通过”mpstat -P ALL 2“命令组合,每隔两秒查看下所有CPU核状态信息,输出信息如下图所示:
![b2b4560bc444f5ef52f1ac107943f256.png](https://i-blog.csdnimg.cn/blog_migrate/cde9efe7297fd1319cb5100393f01e05.jpeg)
其中,%irq为硬中断,%soft为软中断。
从输出可以看出,第三个cpu有61.90%时间在忙于处理中断,跟“cat /proc/interrupts”得到的结果基本一致,整体来看,四核的CPU中,CPU2软中断非常高,看来大部分网络中断请求都交给CPU2来处理了,而其它三个CPU核则非常空闲。
//
配置RPS绑定网卡队列到CPU
//
从上面输出中,可以得到网卡的中断号为16,接着,就可以查询其中断亲缘性配置smp_affinity:
[root@webserver ~]# cat /proc/irq/16/smp_affinity
4
这里的4实际上是十六进制,表示第三个CPU,即为CPU2。这与上面通过命令查看到的结果是一样的。
如何算出来是第三个cpu呢,这要吧16进制的4转换为二进制就能看明白了,如下:
Binary Hex
CPU 0 0001 1
CPU 1 0010 2
CPU 2 0100 4
CPU 3 1000 8
看明白了吧,转换为二进制后,从右到左,看数字1的位置,1在哪个位置,就代表哪个CPU,例如1000,就代表第四个CPU(CPU3 ),同理,如果是10000代表第五个CPU,而10000转换为16进制就是10,第六个CPU二进制就是100000,转为16进制就是20,第七个CPU二进制是1000000,转为16进制就是40,第八个CPU二进制是10000000,转为16进制就是80,依次类推。
了解了这些基本知识,我们可以尝试换一个CPU试试看会发生什么:
echo 1 > /proc/irq/16/smp_affinity_list
然后,再通过”mpstat -P ALL 2“命令观察,会发现处理软中断的CPU变成了CPU0。
知道了smp_affinity输出值的含义,我们可以知道,网卡中断只有某个CPU参与,而其它三个cpu均没有参与中断处理,这很明显是有问题的。
对于高流量Web服务器来说,把不同的网卡队列均衡的绑定到不同的CPU上,相当于将网卡数据包产生的中断负载均衡到不同的CPU上。避免单核处理中断,提高多个 CPU 整体处理中断的能力。对于数据库服务器来说,把网卡绑定到另一个CPU将会提高数据库的响应时间、优化性能。所以,平衡硬件中断有助于提高系统的整体吞吐能力和性能。
那么,如何让多个CPU都参与到中断处理呢,其实可以将smp_affinity设置为f即可,因为f转换为二进制是1111,这表示四个CPU都参与中断处理。执行如下操作:
[root@webserver ~]# echo f > /proc/irq/16/smp_affinity
还可以这样使用类似下面的方法:
[root@webserver ~]# echo 1,3 > /proc/irq/16/smp_affinity_list
[root@webserver ~]# echo 0-7 > /proc/irq/16/smp_affinity_list
安装上面这两个方法设置后,你会发现,中断仍然在一个CPU上,并没有均衡到所有CPU上,原因很简单,因为这是个单队列网卡,对单队列网卡来说,配置smp_affinity和smp_affinity_list多CPU是无效的。
不过,不用担心,办法总是有的,为了充分利用多核cpu,从Centos6.1开始提供了RPS(Receive Packet Steering)和RFS(Receive Flow Steering)功能,通俗点来说就是在软件层面模拟实现硬件的多队列网卡功能。
首先看看如何配置RPS,如果CPU个数是4个的话,可以设置成f,执行如下操作:
[root@webserver ~]# echo f > /sys/class/net/eth0/queues/rx-0/rps_cpus
接着配置内核参数rps_sock_flow_entries(官方文档推荐设置:32768):
[root@webserver ~]# sysctl net.core.rps_sock_flow_entries=32768
最后配置rps_flow_cnt,单队列网卡的话设置成rps_sock_flow_entries即可:
[root@webserver ~]# echo 32768 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt
这里注意,我的云主机网卡标识为eth0,如果你的网卡标识不是这个,请修改上面内核参数对应的网卡设备名称。
做了如上的优化后,我们再运行”mpstat -P ALL 2“命令,可以看到软中断已经分散到了四个CPU了,如下图所示:
![d52022d481e8711eb789bd905aaef94a.png](https://i-blog.csdnimg.cn/blog_migrate/2f8bf47de27efbeec87f2163563cc3ec.jpeg)