雷义芳(智深)
一.背景:
2021年的1月1号,新年伊始的2:27分,突然大数据运维同学在钉钉群中反馈,大数据的slave002节点是不是卡住了。
DBA和运维同学就着手进行排查。
DBA同学反馈,从IDC的大数据集群通过网络拉取阿里云的RDS数据库,确实耗时大幅增加,我们看下图中的Time字段,平时在分钟级别的,今天暴增到了小时级别,网络延时大幅增加。
紧接着运维同学,开始排查IDC到阿里云的网络链路情况,通过阿里云的网络监控可见:
相比正常时间段,网络流入和流出的速率出现了大幅下降,下降约50%。
因为通过网络拉取数据的时间大幅增加,导致大数据集群不能按照正常时间产出数据,整体产出数据的延迟达到3小时,导致一起P2故障,血案发生。
新年伊始,锅从天降。
二.原因分析:
那么问题来了,为什么突然网络是速率会下降约50%呢?接下来还会不会出现这种情况呢?为此我们需要分析到问题的根因,并且彻底解决掉。
因为整个链路很长,出现问题的位置点也很多,所以我们需要逐步确认排查。
1.从源头开始RDS会不会有性能问题导致发送数据过慢?
1.DBA通过阿里云的RDS监控确认,RDS的性能正常。
2.RDS的最大允许传输包参数是否配置不合理导致发送速度过慢?
确认:max_allowed_packet的值为:1073741824 已经是最大值,所以排查这个参数问题。
2.是否是阿里云的VBR或者到网银互联的2条10G的带宽链路有问题导致同步速度变慢?
因为从上面的监控图来看,速率有下降接近50%。
通过运维同学自检和找阿里云工程师确认,VBR和链路本身没有变动,性能正常。
3.网银互联的接入PoP点是否有问题导致链路的速率大幅下降?
网银互联网络工程师确认,并没有变更,也没有做限速操作,从他们内部的监控来看,PoP点的性能正常。
4.海拍客的万兆交换机出现了故障,导致链路的速率大幅下降?
公司网络工程师确认,并没有网络层面的变更。
5.是否是服务器的万兆网卡出现故障或者是服务器的系统的网卡驱动问题导致的速率大幅下降?
登陆服务器查看详情:
[root@prod-hadoop-slave003 test-network]# ifconfig
bond0: flags=5187<UP,BROADCAST,RUNNING,MASTER,MULTICAST> mtu 1500
inet 172.16.40.4 netmask 255.255.255.0 broadcast 172.16.40.255
ether e4:43:4b:17:7a:20 txqueuelen 1000 (Ethernet)
RX packets 742386539453 bytes 810405383622215 (737.0 TiB)
RX errors 0 dropped 37960275 overruns 0 frame 0
TX packets 873066268247 bytes 1179624215433608 (1.0 PiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
可以看到这台服务器有大量的丢包,丢包数达到了:37960275
那么服务器为什么有这么多的丢包呢?
1.是因为服务器的流量太大导致网卡处理不过来丢弃?
我们通过ifconfig命令实时查看服务器的网络流量:
可以看到这台服务器有2块万兆网卡,20Gb的带宽,这里的收发的只有372Mb,远远没有达到服务器的带宽性能瓶颈。
到此为止初步判定原因是在海拍客这端。
2.是否会存在到阿里云的两条10G的链路一条有问题,另外一条又是正常的呢?
因为这次故障中,确实部分服务器拉取速度是正常的,但是部分服务器很慢。
[hadoop@prod-sts001 ~]$ iperf -c 172.16.60.243
------------------------------------------------------------
Client connecting to 172.16.60.243, TCP port 5001
TCP window size: 196 KByte (default)
------------------------------------------------------------
[ 3] local 172.16.50.5 port 52370 connected with 172.16.60.243 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-10.0 sec 1.25 GBytes 1.08 Gbits/sec
[hadoop@prod-hadoop-slave003 ~]$ iperf -c 172.16.60.243
------------------------------------------------------------
Client connecting to 172.16.60.243, TCP port 5001
TCP window size: 119 KByte (default)
------------------------------------------------------------
[ 3] local 172.16.40.4 port 47162 connected with 172.16.60.243 port 5001
[ ID] Interval Transfer Bandwidth
[ 3] 0.0-11.0 sec 3.50 MBytes 2.68 Mbits/sec
通过iperf测试到阿里云的带宽,可以看到其中一次可以跑到1G,但是一次只能跑到2.68M,速度相差巨大。
到此为止可以确认,阿里云侧的链路本身没有问题,那么问题出现在海拍客侧。
海拍客侧的问题方向如下:
1.万兆交换机出现故障,如果服务器走到其中一台故障交换机速度就会大幅下降,否则速度就正常?
登陆交换机查看交换机状态:
10GE1/0/5 current state : UP (ifindex: 9)
Line protocol current state : UP
Description:
Switch Port, TPID : 8100(Hex), The Maximum Frame Length is 9216
IP Sending Frames' Format is PKTFMT_ETHNT_2, Hardware address is 70c7-f288-eea1
Port Mode: COMMON FIBER, Port Split/Aggregate: DISABLE
Speed: 10000, Loopback: NONE
Duplex: FULL, Negotiation: DISABLE
Input Flow-control: DISABLE, Output Flow-control: DISABLE
Mdi: -, Fec: NONE
Last physical up time : 2020-12-31 08:21:59
Last physical down time : 2020-12-31 08:21:56
Current system time: 2021-01-02 01:57:18
Statistics last cleared:never
Last 300 seconds input rate: 127192732 bits/sec, 11808 packets/sec
Last 300 seconds output rate: 129829834 bits/sec, 16101 packets/sec
Input peak rate 2783748476 bits/sec, Record time: 2020-09-02 02:29:24
Output peak rate 5275362007 bits/sec, Record time: 2020-07-24 14:50:26
Input : 602685669157716 bytes, 438332459970 packets
Output: 416614335185060 bytes, 373410018051 packets
Input:
Unicast: 438219669215, Multicast: 1
Broadcast: 15, Jumbo: 0
Discard: 0, Frames: 0
Pause: 6280
Total Error: 122669372
CRC: 112432769, Giants: 0
Jabbers: 65563, Fragments: 286127
Runts: 0, DropEvents: 0
Alignments: 0, Symbols: 9884913
Ignoreds: 0
Output:
Unicast: 373389982764, Multicast: 19139024
Broadcast: 896263, Jumbo: 0
Discard: 5779756, Buffers Purged: 0
Pause: 0
Input bandwidth utilization threshold : 90.00%
Output bandwidth utilization threshold: 90.00%
Last 300 seconds input utility rate: 1.27%
Last 300 seconds output utility rate: 1.29%
可以看到交换机物理接口上面,10GE1/0/5端口有down过。
有大量的错误,并且主要是CRC的错误,有CRC的错误表示物理链路层面的故障,要么是光模块问题,端口问题,或者模块和设备不兼容。
还可以看到最近300秒,万兆带宽的利用率很低,只有1.2%左右。
建议机房人员更换光模块,因为端口在2020-12-31 08:21:56 down过。
但是因为机房没有备用的光模块,所以无法更换,只能先拔出来,不用,排除掉这个问题。
CRC校验:
循环冗余校验(Cyclic Redundancy Check, CRC)是一种根据网络数据包或计算机文件等数据产生简短固定位数校验码的一种信道编码技术,主要用来检测或校验数据传输或者保存后可能出现的错误。它是利用除法及余数的原理来作错误侦测的。
在数据传输过程中,无论传输系统的设计再怎么完美,差错总会存在,这种差错可能会导致在链路上传输的一个或者多个帧被破坏(出现比特差错,0变为1,或者1变为0),从而接受方接收到错误的数据。
为尽量提高接受方收到数据的正确率,在接收方接收数据之前需要对数据进行差错检测,当且仅当检测的结果为正确时接收方才真正收下数据。
发送方计算机使用某公式计算出被传送数据所含信息的一个值,并将此值 附在被传送数据后,接收方计算机则对同一数据进行 相同的计算,应该得到相同的结果。如果这两个 CRC结果不一致,则说明发送中出现了差错,接收方计算机可要求发送方计算机重新发送该数据。
2.服务器连接万兆交换机的2条光纤其中一条出现故障或者光模块出现故障,如果请求到了这条光纤或者这个光模块就会速度大幅下降?
IDC工程师确认,光纤是有光的出来,排除掉光纤的问题。
3.服务器的性能问题严重或者其他异常问题,导致无法及时处理网络的数据包收发,导致网络数据包收发的速率不稳定?
登陆服务器确认,服务器此时性能并没有问题,所以排除掉性能问题。
通过系统的/var/log/messages日志和dmesg确认,此时系统并没有异常。
IDC工程师拔掉了10GE1/0/5这个端口的光模块后,我们再次测试网络速度:
[root@prod-hadoop-slave003 test-network]# iperf3 -c 172.16.6.188 -b 1G -t 15 -P 2 -p 10000
Connecting to host 172.16.6.188, port 10000
[ 4] local 172.16.40.4 port 32806 connected to 172.16.6.188 port 10000
[ 6] local 172.16.40.4 port 32808 connected to 172.16.6.188 port 10000
[ ID] Interval Transfer Bandwidth Retr Cwnd
[ 4] 0.00-1.00 sec 107 MBytes 894 Mbits/sec 778 38.2 KBytes
[ 6] 0.00-1.00 sec 115 MBytes 968 Mbits/sec 763 137 KBytes
[SUM] 0.00-1.00 sec 222 MBytes 1.86 Gbits/sec 1541
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 1.00-2.00 sec 32.8 MBytes 275 Mbits/sec 393 91.9 KBytes
[ 6] 1.00-2.00 sec 84.9 MBytes 712 Mbits/sec 395 91.9 KBytes
[SUM] 1.00-2.00 sec 118 MBytes 987 Mbits/sec 788
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 2.00-3.00 sec 61.6 MBytes 517 Mbits/sec 326 60.8 KBytes
[ 6] 2.00-3.00 sec 55.4 MBytes 465 Mbits/sec 426 76.4 KBytes
[SUM] 2.00-3.00 sec 117 MBytes 981 Mbits/sec 752
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 3.00-4.00 sec 53.6 MBytes 448 Mbits/sec 323 105 KBytes
[ 6] 3.00-4.00 sec 62.9 MBytes 525 Mbits/sec 367 93.3 KBytes
[SUM] 3.00-4.00 sec 116 MBytes 973 Mbits/sec 690
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 4.00-5.00 sec 60.0 MBytes 506 Mbits/sec 328 126 KBytes
[ 6] 4.00-5.00 sec 57.8 MBytes 487 Mbits/sec 292 99.0 KBytes
[SUM] 4.00-5.00 sec 118 MBytes 992 Mbits/sec 620
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 5.00-6.00 sec 55.4 MBytes 465 Mbits/sec 332 97.6 KBytes
[ 6] 5.00-6.00 sec 61.8 MBytes 518 Mbits/sec 351 49.5 KBytes
[SUM] 5.00-6.00 sec 117 MBytes 983 Mbits/sec 683
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 6.00-7.00 sec 73.2 MBytes 614 Mbits/sec 353 70.7 KBytes
[ 6] 6.00-7.00 sec 43.4 MBytes 364 Mbits/sec 326 82.0 KBytes
[SUM] 6.00-7.00 sec 117 MBytes 978 Mbits/sec 679
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 7.00-8.00 sec 61.1 MBytes 513 Mbits/sec 264 182 KBytes
[ 6] 7.00-8.00 sec 51.8 MBytes 434 Mbits/sec 308 103 KBytes
[SUM] 7.00-8.00 sec 113 MBytes 947 Mbits/sec 572
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 8.00-9.00 sec 69.4 MBytes 582 Mbits/sec 387 132 KBytes
[ 6] 8.00-9.00 sec 52.0 MBytes 436 Mbits/sec 495 90.5 KBytes
[SUM] 8.00-9.00 sec 121 MBytes 1.02 Gbits/sec 882
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 9.00-10.00 sec 59.9 MBytes 502 Mbits/sec 305 77.8 KBytes
[ 6] 9.00-10.00 sec 57.4 MBytes 481 Mbits/sec 434 83.4 KBytes
[SUM] 9.00-10.00 sec 117 MBytes 984 Mbits/sec 739
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 10.00-11.00 sec 53.1 MBytes 446 Mbits/sec 255 53.7 KBytes
[ 6] 10.00-11.00 sec 63.5 MBytes 533 Mbits/sec 328 82.0 KBytes
[SUM] 10.00-11.00 sec 117 MBytes 978 Mbits/sec 583
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 11.00-12.00 sec 54.4 MBytes 456 Mbits/sec 282 119 KBytes
[ 6] 11.00-12.00 sec 63.1 MBytes 530 Mbits/sec 343 105 KBytes
[SUM] 11.00-12.00 sec 118 MBytes 986 Mbits/sec 625
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 12.00-13.00 sec 56.8 MBytes 476 Mbits/sec 275 119 KBytes
[ 6] 12.00-13.00 sec 58.8 MBytes 493 Mbits/sec 337 77.8 KBytes
[SUM] 12.00-13.00 sec 116 MBytes 969 Mbits/sec 612
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 13.00-14.00 sec 72.6 MBytes 609 Mbits/sec 374 94.7 KBytes
[ 6] 13.00-14.00 sec 45.9 MBytes 385 Mbits/sec 425 100 KBytes
[SUM] 13.00-14.00 sec 118 MBytes 994 Mbits/sec 799
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 14.00-15.00 sec 56.9 MBytes 477 Mbits/sec 294 46.7 KBytes
[ 6] 14.00-15.00 sec 60.2 MBytes 505 Mbits/sec 363 119 KBytes
[SUM] 14.00-15.00 sec 117 MBytes 982 Mbits/sec 657
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-15.00 sec 927 MBytes 519 Mbits/sec 5269 sender
[ 4] 0.00-15.00 sec 925 MBytes 517 Mbits/sec receiver
[ 6] 0.00-15.00 sec 934 MBytes 522 Mbits/sec 5953 sender
[ 6] 0.00-15.00 sec 931 MBytes 521 Mbits/sec receiver
[SUM] 0.00-15.00 sec 1.82 GBytes 1.04 Gbits/sec 11222 sender
[SUM] 0.00-15.00 sec 1.81 GBytes 1.04 Gbits/sec receiver
iperf Done.
可以看到速度恢复正常,业务方再没有反馈速度慢的问题。
但是不能就此确认,网络就已经恢复正常。
怎么能够确认网络是正常的呢?我们怎么衡量网络的性能指标?
性能指标回顾
在评估网络性能前,我们先来回顾一下,衡量网络性能的指标。
首先,带宽,表示链路的最大传输速率,单位是 b/s(比特 / 秒)。
为服务器选购网卡时,带宽就是最核心的参考指标。常用的带宽有 1000M、10G、40G、100G 等。
第二,吞吐量,表示没有丢包时的最大数据传输速率,单位通常为 b/s (比特 / 秒)或者 B/s(字节 / 秒)。吞吐量受带宽的限制,吞吐量 / 带宽也就是该网络链路的使用率。
第三,延时,表示从网络请求发出后,一直到收到远端响应,所需要的时间延迟。
这个指标在不同场景中可能会有不同的含义。它可以表示建立连接需要的时间(比如 TCP 握手延时),或者一个数据包往返所需时间(比如 RTT)。
最后,PPS,是 Packet Per Second(包 / 秒)的缩写,表示以网络包为单位的传输速率。
PPS 通常用来评估网络的转发能力,而基于 Linux 服务器的转发,很容易受到网络包大小的影响(交换机通常不会受到太大影响,即交换机可以线性转发)。
这四个指标中,带宽跟物理网卡配置是直接关联的。一般来说,网卡确定后,带宽也就确定了(当然,实际带宽会受限于整个网络链路中最小的那个模块)。
最后的 PPS,则是以网络包为单位的网络传输速率,通常用在需要大量转发的场景中。而对 TCP 或者 Web 服务来说,更多会用并发连接数和每秒请求数(QPS,Query per Second)等指标,它们更能反应实际应用程序的性能。
网卡转发性能测试:
网络接口层和网络层,它们主要负责网络包的封装、寻址、路由以及发送和接收。在这两个网络协议层中,每秒可处理的网络包数 PPS,就是最重要的性能指标。特别是 64B 小包的处理能力,值得我们特别关注。
那么,如何来测试网络包的处理能力呢?
Linux 内核自带的高性能网络测试工具 pktgen。pktgen 支持丰富的自定义选项,方便你根据实际需要构造所需网络包,从而更准确地测试出目标服务器的性能。
不过,在 Linux 系统中,你并不能直接找到 pktgen 命令。因为 pktgen 作为一个内核线程来运行,需要你加载 pktgen 内核模块后,再通过 /proc 文件系统来交互。
下面就是 pktgen 启动的72个内核线程和 /proc 文件系统的交互文件:
modprobe pktgen
ps -ef | grep pktgen | grep -v grep
[root@prod-hadoop-slave003 ~]# ps -ef | grep pktgen | grep -v grep
root 170104 2 0 01:22 ? 00:00:00 [kpktgend_0]
root 170105 2 0 01:22 ? 00:00:00 [kpktgend_1]
root 170106 2 0 01:22 ? 00:00:00 [kpktgend_2]
root 170107 2 0 01:22 ? 00:00:00 [kpktgend_3]
root 170108 2 0 01:22 ? 00:00:00 [kpktgend_4]
root 170109 2 0 01:22 ? 00:00:00 [kpktgend_5]
root 170110 2 0 01:22 ? 00:00:00 [kpktgend_6]
root 170111 2 0 01:22 ? 00:00:00 [kpktgend_7]
root 170112 2 0 01:22 ? 00:00:00 [kpktgend_8]
root 170113 2 0 01:22 ? 00:00:00 [kpktgend_9]
root 170114 2 0 01:22 ? 00:00:00 [kpktgend_10]
root 170115 2 0 01:22 ? 00:00:00 [kpktgend_11]
root 170116 2 0 01:22 ? 00:00:00 [kpktgend_12]
root 170117 2 0 01:22 ? 00:00:00 [kpktgend_13]
root 170118 2 0 01:22 ? 00:00:00 [kpktgend_14]
root 170119 2 0 01:22 ? 00:00:00 [kpktgend_15]
root 170120 2 0 01:22 ? 00:00:00 [kpktgend_16]
root 170121 2 0 01:22 ? 00:00:00 [kpktgend_17]
root 170122 2 0 01:22 ? 00:00:00 [kpktgend_18]
root 170123 2 0 01:22 ? 00:00:00 [kpktgend_19]
root 170125 2 0 01:22 ? 00:00:00 [kpktgend_20]
root 170126 2 0 01:22 ? 00:00:00 [kpktgend_21]
root 170127 2 0 01:22 ? 00:00:00 [kpktgend_22]
root 170128 2 0 01:22 ? 00:00:00 [kpktgend_23]
root 170129 2 0 01:22 ? 00:00:00 [kpktgend_24]
root 170130 2 0 01:22 ? 00:00:00 [kpktgend_25]
root 170131 2 0 01:22 ? 00:00:00 [kpktgend_26]
root 170132 2 0 01:22 ? 00:00:00 [kpktgend_27]
root 170133 2 0 01:22 ? 00:00:00 [kpktgend_28]
root 170134 2 0 01:22 ? 00:00:00 [kpktgend_29]
root 170135 2 0 01:22 ? 00:00:00 [kpktgend_30]
root 170137 2 0 01:22 ? 00:00:00 [kpktgend_31]
root 170138 2 0 01:22 ? 00:00:00 [kpktgend_32]
root 170139 2 0 01:22 ? 00:00:00 [kpktgend_33]
root 170140 2 0 01:22 ? 00:00:00 [kpktgend_34]
root 170141 2 0 01:22 ? 00:00:00 [kpktgend_35]
root 170143 2 0 01:22 ? 00:00:00 [kpktgend_36]
root 170144 2 0 01:22 ? 00:00:00 [kpktgend_37]
root 170145 2 0 01:22 ? 00:00:00 [kpktgend_38]
root 170146 2 0 01:22 ? 00:00:00 [kpktgend_39]
root 170148 2 0 01:22 ? 00:00:00 [kpktgend_40]
root 170149 2 0 01:22 ? 00:00:00 [kpktgend_41]
root 170150 2 0 01:22 ? 00:00:00 [kpktgend_42]
root 170151 2 0 01:22 ? 00:00:00 [kpktgend_43]
root 170152 2 0 01:22 ? 00:00:00 [kpktgend_44]
root 170153 2 0 01:22 ? 00:00:00 [kpktgend_45]
root 170154 2 0 01:22 ? 00:00:00 [kpktgend_46]
root 170155 2 0 01:22 ? 00:00:00 [kpktgend_47]
root 170156 2 0 01:22 ? 00:00:00 [kpktgend_48]
root 170157 2 0 01:22 ? 00:00:00 [kpktgend_49]
root 170158 2 0 01:22 ? 00:00:00 [kpktgend_50]
root 170159 2 0 01:22 ? 00:00:00 [kpktgend_51]
root 170160 2 0 01:22 ? 00:00:00 [kpktgend_52]
root 170161 2 0 01:22 ? 00:00:00 [kpktgend_53]
root 170162 2 0 01:22 ? 00:00:00 [kpktgend_54]
root 170163 2 0 01:22 ? 00:00:00 [kpktgend_55]
root 170164 2 0 01:22 ? 00:00:00 [kpktgend_56]
root 170165 2 0 01:22 ? 00:00:00 [kpktgend_57]
root 170166 2 0 01:22 ? 00:00:00 [kpktgend_58]
root 170167 2 0 01:22 ? 00:00:00 [kpktgend_59]
root 170168 2 0 01:22 ? 00:00:00 [kpktgend_60]
root 170169 2 0 01:22 ? 00:00:00 [kpktgend_61]
root 170170 2 0 01:22 ? 00:00:00 [kpktgend_62]
root 170171 2 0 01:22 ? 00:00:00 [kpktgend_63]
root 170172 2 0 01:22 ? 00:00:00 [kpktgend_64]
root 170173 2 0 01:22 ? 00:00:00 [kpktgend_65]
root 170174 2 0 01:22 ? 00:00:00 [kpktgend_66]
root 170175 2 0 01:22 ? 00:00:00 [kpktgend_67]
root 170176 2 0 01:22 ? 00:00:00 [kpktgend_68]
root 170177 2 0 01:22 ? 00:00:00 [kpktgend_69]
root 170178 2 0 01:22 ? 00:00:00 [kpktgend_70]
root 170180 2 0 01:22 ? 00:00:00 [kpktgend_71]
ls /proc/net/pktgen/
[root@prod-hadoop-slave003 ~]# ls /proc/net/pktgen/
kpktgend_0 kpktgend_15 kpktgend_21 kpktgend_28 kpktgend_34 kpktgend_40 kpktgend_47 kpktgend_53 kpktgend_6 kpktgend_66 kpktgend_8
kpktgend_1 kpktgend_16 kpktgend_22 kpktgend_29 kpktgend_35 kpktgend_41 kpktgend_48 kpktgend_54 kpktgend_60 kpktgend_67 kpktgend_9
kpktgend_10 kpktgend_17 kpktgend_23 kpktgend_3 kpktgend_36 kpktgend_42 kpktgend_49 kpktgend_55 kpktgend_61 kpktgend_68 pgctrl
kpktgend_11 kpktgend_18 kpktgend_24 kpktgend_30 kpktgend_37 kpktgend_43 kpktgend_5 kpktgend_56 kpktgend_62 kpktgend_69
kpktgend_12 kpktgend_19 kpktgend_25 kpktgend_31 kpktgend_38 kpktgend_44 kpktgend_50 kpktgend_57 kpktgend_63 kpktgend_7
kpktgend_13 kpktgend_2 kpktgend_26 kpktgend_32 kpktgend_39 kpktgend_45 kpktgend_51 kpktgend_58 kpktgend_64 kpktgend_70
kpktgend_14 kpktgend_20 kpktgend_27 kpktgend_33 kpktgend_4 kpktgend_46 kpktgend_52 kpktgend_59 kpktgend_65 kpktgend_71
pktgen 在每个 CPU 上启动一个内核线程,并可以通过 /proc/net/pktgen 下面的同名文件,跟这些线程交互;而 pgctrl 则主要用来控制这次测试的开启和停止。
如果 modprobe 命令执行失败,说明你的内核没有配置 CONFIG_NET_PKTGEN 选项。这就需要你配置 pktgen 内核模块(即 CONFIG_NET_PKTGEN=m)后,重新编译内核,才可以使用。
以发包测试为例,假设发包机器使用的网卡是 em1,而目标机器的 IP 地址为 172.16.6.188,MAC 地址为 00:16:3f:00:bc:fa。
测试脚本:
#!/bin/bash
# This script is used to test network card pps performance.
# Author: leiyifang
# History: First release 20200102
# 定义一个工具函数,方便后面配置各种测试选项
function pgset() {
local result
echo $1 > $PGDEV
result=`cat $PGDEV | fgrep "Result: OK:"`
if [ "$result" = "" ]; then
cat $PGDEV | fgrep Result:
fi
}
# 为0号线程绑定eth0网卡
PGDEV=/proc/net/pktgen/kpktgend_0
pgset "rem_device_all" # 添加em1网卡
pgset "add_device em1" # 添加em1网卡
# 配置eth0网卡的测试选项
PGDEV=/proc/net/pktgen/em1
pgset "count 1000000" # 总发包数量
pgset "delay 5000" # 不同包之间的发送延迟(单位纳秒)
pgset "clone_skb 0" # SKB包复制
pgset "pkt_size 64" # 网络包大小
pgset "dst 172.16.6.188" # 目的IP
pgset "dst_mac 00:16:3f:00:bc:fa" # 目的MAC
# 启动测试
PGDEV=/proc/net/pktgen/pgctrl
pgset "start"
测试:
sh test-network-pps.sh
稍等一会儿,测试完成后,结果可以从 /proc 文件系统中获取。通过下面代码段中的内容,我们可以查看刚才的测试报告:
结果如下:
cat /proc/net/pktgen/em1
Params: count 1000000 min_pkt_size: 64 max_pkt_size: 64
frags: 0 delay: 5000 clone_skb: 0 ifname: em1
flows: 0 flowlen: 0
queue_map_min: 0 queue_map_max: 0
dst_min: 172.16.6.188 dst_max:
src_min: src_max:
src_mac: e4:43:4b:17:7a:20 dst_mac: 00:16:3f:00:bc:fa
udp_src_min: 9 udp_src_max: 9 udp_dst_min: 9 udp_dst_max: 9
src_mac_count: 0 dst_mac_count: 0
Flags:
Current:
pkts-sofar: 1000000 errors: 0
started: 18195222386021us stopped: 18195227386083us idle: 4401664us
seq_num: 1000001 cur_dst_mac_offset: 0 cur_src_mac_offset: 0
cur_saddr: 0.0.0.0 cur_daddr: 172.16.6.188
cur_udp_dst: 9 cur_udp_src: 9
cur_queue_map: 0
flows: 0
Result: OK: 5000062(c598398+d4401664) usec, 1000000 (64byte,0frags)
199997pps 102Mb/sec (102398464bps) errors: 0
你可以看到,测试报告主要分为三个部分:
第一部分的 Params 是测试选项;
第二部分的 Current 是测试进度,其中, packts so far(pkts-sofar)表示已经发送了 100 万个包,也就表明测试已完成。
第三部分的 Result 是测试结果,包含测试所用时间、网络包数量和分片、PPS、吞吐量以及错误数。
根据上面的结果,我们发现,PPS 为 19 万,吞吐量为 102 Mb/s,没有发生错误。
那么,19万的 PPS 好不好呢?作为对比,可以计算一下千兆交换机的 PPS。交换机可以达到线速(满负载时,无差错转发),它的 PPS 就是 1000Mbit 除以以太网帧的大小,即 1000Mbps/((64+20)*8bit) = 1.5 Mpps(其中,20B 为以太网帧前导和帧间距的大小)。
即使是千兆交换机的 PPS,也可以达到 150 万 PPS,比我们测试得到的 19 万大多了。
虽然这个结果并不好,但是目前是可以满足数据组的需求的,暂时没有优化的必要。
TCP性能:
yum install iperf3
在目标机器上启动 iperf 服务端(ansible)
iperf3 -s -i 1 -p 10000
接着,在另一台机器上运行 iperf 客户端,运行测试:
# -c表示启动客户端,192.168.0.30为目标服务器的IP
# -b表示目标带宽(单位是bits/s)
# -t表示测试时间# -P表示并发数,-p表示目标服务器监听端口
$ iperf3 -c 172.16.6.188 -b 1G -t 15 -P 2 -p 10000
稍等一会儿(15 秒)测试结束后,回到目标服务器,查看 iperf 的报告:
去掉网卡bond之后的测试结果:
[root@prod-hadoop-slave003 test-network]# iperf3 -c 172.16.6.188 -b 1G -t 15 -P 2 -p 10000
Connecting to host 172.16.6.188, port 10000
[ 4] local 172.16.40.4 port 32806 connected to 172.16.6.188 port 10000
[ 6] local 172.16.40.4 port 32808 connected to 172.16.6.188 port 10000
[ ID] Interval Transfer Bandwidth Retr Cwnd
[ 4] 0.00-1.00 sec 107 MBytes 894 Mbits/sec 778 38.2 KBytes
[ 6] 0.00-1.00 sec 115 MBytes 968 Mbits/sec 763 137 KBytes
[SUM] 0.00-1.00 sec 222 MBytes 1.86 Gbits/sec 1541
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 1.00-2.00 sec 32.8 MBytes 275 Mbits/sec 393 91.9 KBytes
[ 6] 1.00-2.00 sec 84.9 MBytes 712 Mbits/sec 395 91.9 KBytes
[SUM] 1.00-2.00 sec 118 MBytes 987 Mbits/sec 788
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 2.00-3.00 sec 61.6 MBytes 517 Mbits/sec 326 60.8 KBytes
[ 6] 2.00-3.00 sec 55.4 MBytes 465 Mbits/sec 426 76.4 KBytes
[SUM] 2.00-3.00 sec 117 MBytes 981 Mbits/sec 752
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 3.00-4.00 sec 53.6 MBytes 448 Mbits/sec 323 105 KBytes
[ 6] 3.00-4.00 sec 62.9 MBytes 525 Mbits/sec 367 93.3 KBytes
[SUM] 3.00-4.00 sec 116 MBytes 973 Mbits/sec 690
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 4.00-5.00 sec 60.0 MBytes 506 Mbits/sec 328 126 KBytes
[ 6] 4.00-5.00 sec 57.8 MBytes 487 Mbits/sec 292 99.0 KBytes
[SUM] 4.00-5.00 sec 118 MBytes 992 Mbits/sec 620
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 5.00-6.00 sec 55.4 MBytes 465 Mbits/sec 332 97.6 KBytes
[ 6] 5.00-6.00 sec 61.8 MBytes 518 Mbits/sec 351 49.5 KBytes
[SUM] 5.00-6.00 sec 117 MBytes 983 Mbits/sec 683
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 6.00-7.00 sec 73.2 MBytes 614 Mbits/sec 353 70.7 KBytes
[ 6] 6.00-7.00 sec 43.4 MBytes 364 Mbits/sec 326 82.0 KBytes
[SUM] 6.00-7.00 sec 117 MBytes 978 Mbits/sec 679
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 7.00-8.00 sec 61.1 MBytes 513 Mbits/sec 264 182 KBytes
[ 6] 7.00-8.00 sec 51.8 MBytes 434 Mbits/sec 308 103 KBytes
[SUM] 7.00-8.00 sec 113 MBytes 947 Mbits/sec 572
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 8.00-9.00 sec 69.4 MBytes 582 Mbits/sec 387 132 KBytes
[ 6] 8.00-9.00 sec 52.0 MBytes 436 Mbits/sec 495 90.5 KBytes
[SUM] 8.00-9.00 sec 121 MBytes 1.02 Gbits/sec 882
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 9.00-10.00 sec 59.9 MBytes 502 Mbits/sec 305 77.8 KBytes
[ 6] 9.00-10.00 sec 57.4 MBytes 481 Mbits/sec 434 83.4 KBytes
[SUM] 9.00-10.00 sec 117 MBytes 984 Mbits/sec 739
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 10.00-11.00 sec 53.1 MBytes 446 Mbits/sec 255 53.7 KBytes
[ 6] 10.00-11.00 sec 63.5 MBytes 533 Mbits/sec 328 82.0 KBytes
[SUM] 10.00-11.00 sec 117 MBytes 978 Mbits/sec 583
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 11.00-12.00 sec 54.4 MBytes 456 Mbits/sec 282 119 KBytes
[ 6] 11.00-12.00 sec 63.1 MBytes 530 Mbits/sec 343 105 KBytes
[SUM] 11.00-12.00 sec 118 MBytes 986 Mbits/sec 625
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 12.00-13.00 sec 56.8 MBytes 476 Mbits/sec 275 119 KBytes
[ 6] 12.00-13.00 sec 58.8 MBytes 493 Mbits/sec 337 77.8 KBytes
[SUM] 12.00-13.00 sec 116 MBytes 969 Mbits/sec 612
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 13.00-14.00 sec 72.6 MBytes 609 Mbits/sec 374 94.7 KBytes
[ 6] 13.00-14.00 sec 45.9 MBytes 385 Mbits/sec 425 100 KBytes
[SUM] 13.00-14.00 sec 118 MBytes 994 Mbits/sec 799
- - - - - - - - - - - - - - - - - - - - - - - - -
[ 4] 14.00-15.00 sec 56.9 MBytes 477 Mbits/sec 294 46.7 KBytes
[ 6] 14.00-15.00 sec 60.2 MBytes 505 Mbits/sec 363 119 KBytes
[SUM] 14.00-15.00 sec 117 MBytes 982 Mbits/sec 657
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-15.00 sec 927 MBytes 519 Mbits/sec 5269 sender
[ 4] 0.00-15.00 sec 925 MBytes 517 Mbits/sec receiver
[ 6] 0.00-15.00 sec 934 MBytes 522 Mbits/sec 5953 sender
[ 6] 0.00-15.00 sec 931 MBytes 521 Mbits/sec receiver
[SUM] 0.00-15.00 sec 1.82 GBytes 1.04 Gbits/sec 11222 sender
[SUM] 0.00-15.00 sec 1.81 GBytes 1.04 Gbits/sec receiver
iperf Done.
最后的 SUM 行就是测试的汇总结果,包括测试时间、数据传输量以及带宽等。
按照发送和接收,这一部分又分为了 sender 和 receiver 两行。
从测试结果你可以看到,这台机器 TCP 接收的带宽(吞吐量)为 1.04 Gbits/sec,因为阿里云的服务器是1G的带宽,IDC的服务器是10G的带宽,所以这里测试出来是阿里云的服务器可以到达1.04G的带宽,符合预期。
因为测试了4次,每次都可以达到这个带宽,所以初步确定了网络已经稳定,而不是像开始测试的那样,一次1G,一次2M。
到此为止,是时候总结导致这次故障的根因:
1.因为IDC中,prod-hadoop-slave003这台服务器连接的万兆交换机上面的10GE1/0/5这个万兆网卡使用光模块,有严重的光衰问题(此时并没有坏,而且端口的状态是UP的),服务器发流量走到这个模块上后,因为光衰严重
所以交换机做CRC校验的时候就大量的校验结果不一致的包会被丢弃,只有1.3%的数据包通过了,导致整体的收发速率大幅下降,表现出来就是从阿里云的RDS数据库拉取数据的时候,速度特别慢。
2.因为数据拉取慢,导致大量数据没有被及时拉取过来,等数据拉取过来后,还需要经过大量的计算才能产出结果,这个就导致了最终产出结果数据的时间被推迟,最终导致故障。
三,解决方案:
1.更换掉出现故障的万兆光模块,问题解决。
2.购买一批万兆光纤模块作为备用放在IDC机房,后续检测到故障后,可以进行及时的替换。
3.监控系统添加上对CRC校验措施的监控和报警,增加对丢包的监控和报警。
4.后续考虑上线基于应用层面的监控和报警系统。
四,后续的技术畅想:
上面的分析还是有部分问题没有解释清楚:
1.为什么光模块都光衰了,万兆交换机没有把他禁用掉?
因为万兆交换机检测的是电信号,此时光模块是通电状态,是有电信号的,并且还有数据包在收发,所以不会禁用。
如果此时光模块是彻底的坏了,没有电信号了,此时万兆交换机的端口就会变成down的状态,那么数据包就不会走到这条链路上来。
2.为什么服务器本身就做了网卡绑定,出现了大量丢包,服务器没有把这块网卡踢掉,走正常的网卡?
虽然这个网卡对应的光模块有严重的光衰,但是服务器网卡绑定判定网卡状态是否正常的使用的ICMP协议,也就是我们常说的Ping检测,如果ping检测是通的,那么它还是认为这个网卡链路是正常的,不会剔除。
如果此时光模块是彻底的坏了,没有电信号了,网卡对应的链路无法ping通,是会把它踢出绑定的虚拟网卡。
3.针对上面的这类问题,除了常规的监控和报警之外还有什么好解决方案,能够及时告警出来,降低排查的难度,缩短排查的时间,让业务可以快速感知到,快速恢复?
两个问题:
3.1 目前的网络模型TCP/IP,是分层的,各个层负责自己的职责,但是没有一个层为最终的应用层结果负责。
可以看到这次的故障,应用层的大数据应用都已经受到严重的影响,但是TCP/IP模型的每个层级都没有机制处理这类问题。
当然,如果大数据应用层能够检测到这类问题,自动的把这个节点从集群中踢出,那么问题也是可以得到解决。
3.2 常规的网络监控都是基于硬件,基于ICMP协议对于这类光衰的问题,无法检测到,当然也无法做到自愈。
我们自己的IDC机房规模并不大,只有几十台服务器,那么微软,谷歌,阿里巴巴他们的机房的服务器规模都是10万台起步,他们又是怎么解决这类问题的呢?
这里就需要我们做思路的转变,不再使用传统的网络分层的思路来做监控和报警,而使用应用层面的视角来做监控和报警。
1.因为机房底层涉及到的设备多,厂家多,而且每个厂家都有自己的系统,自己的固件,我们想穷尽这么多设备,这么厂家的,这么多的系统,固件的监控项,风险项成本是非常大的,在我们公司2个运维工程师的情况下,
这个思路是不可取的,也是无法落地的。
2.我们可以从应用层的维度来做监控,我们可以使用TCP层面来做监控,不再使用ICMP协议。
基本的思路是,我们把整个IDC作为一个交织的网络大网,这个大网之间只要TCP的网络是通,网络质量的符合我们要求的,那么我们就判定为网络质量正常,其他的情况都是异常,我们就需要做报警,做后续的处理。
基于这个思路,我们参考行业的解决方案,我们可以看到微软公司给出了PingMesh的解决方案。
服务器之间的网络质量,如果服务器之间的网络质量异常,那么就进行报警。
因为服务器之间的通信是经过网络设备,所以从服务器的TCP层面的通信质量来评估,也就评估到底层的网络质量,关注在TCP层的网络质量,通常就可以关注到底层的网络质量,因为我们的java应用,
无论的大数据技术栈还是Dubbo技术栈都是基于TCP之上的应用。
想说的话:
如今我们生活在一个严重依赖网络的时代,依赖大数据的时代,但是我们使用的底层网络技术栈其实和20年前并没有太大的进步,而基于系统(k8s,servicemesh)和应用层面(dubbo,springcloud)的技术栈和生态却日益完善。
在这个背景下,我们怎么保障底层的网络能够稳定,出现问题能够快速发现,快速恢复,就是一个很大的挑战。
基于微软的PingMesh论文,启发我们,应该在以前传统的监控和报警的基础上,需要往上走到应用层,应用层使用什么协议,我们就需要使用什么协议为基准进行监控,现在使用TCP,那么就需要基于TCP的监控和报警。
如果后续大规模使用了HTTP 3也就是UDP,那么我们的监控系统就需要使用UDP为基准进行监控和报警,为最终的应用体验负责。
五,参考资料:
极客时间网络性能评估:
https://time.geekbang.org/column/article/81497
微软论文:
开源PingMesh项目: