某日研发中心一同事反馈系统访问发生异常,时不时的会出现系统打不开现象。出现生产问题影响业务正常运行,自然是紧急响应,遂配合研发同事一起排查和处理,整个过程一波三折,总结下来该案例还是挺有意思的。
会同研发同事一起梳理业务系统故障相关信息后,整理说明如下:
因为在测试环境中系统使用正常,而生产环境却出现问题的缘故,所以研发同事一开始就怀疑网络有问题,情何以堪,咋能这样判断呢?锅从天上来,当然不能随随便便接之。简单了解了下问题发生的同时,两端服务器的 Ping 等其他监控均是正常的,心里感觉踏实了一半,隐约感觉不像是网络的问题。
因为网络在重点 DMZ 区域部署有 NPM (刚好是客户端所在接入交换机上的镜像节点),所以根据所提供的故障时间点和业务 IP 通讯对回溯了该流量,进入实质分析。
通过 NPM 回溯分析设备导出的数据包文件,基本信息如下:
λ capinfos test.pcapng
File name: test.pcapng
File type: Wireshark/... - pcapng
File encapsulation: Ethernet
File timestamp precision: nanoseconds (9)
Packet size limit: file hdr: (not set)
Packet size limit: inferred: 70 bytes - 1518 bytes (range)
Number of packets: 6463
File size: 2174 kB
Data size: 1906 kB
Capture duration: 5990.797626192 seconds
First packet time: 2022-11-18 16:45:07.192079642
Last packet time: 2022-11-18 18:24:57.989705834
Data byte rate: 318 bytes/s
Data bit rate: 2545 bits/s
Average packet size: 294.95 bytes
Average packet rate: 1 packets/s
SHA256: e97bbdffd9f98d0805737cb93d6d8255acd045241aa716a8af3966b0ae5ca76f
RIPEMD160: 0329186f9145dcf38fac739077219a3d93298b34
SHA1: 9a3f06a04163f388b8800889d46fe3db04453c26
Strict time order: True
Capture comment: Sanitized by TraceWrangler v0.6.8 build 949
Number of interfaces in file: 1
Interface #0 info:
Encapsulation = Ethernet (1 - ether)
Capture length = 2048
Time precision = nanoseconds (9)
Time ticks per second = 1000000000
Time resolution = 0x09
Number of stat entries = 0
Number of packets = 6463
数据包文件通过 NPM 回溯分析下载,并根据 IP 通讯对做过特定过滤,且经过 TraceWrangler 匿名化软件处理。捕获总时长 5990 秒,数据包数量 6463 个,速率 2545 bps 很低。
- 关于 TraceWrangler 匿名化软件简介,可以查看之前的文章《Wireshark 提示和技巧 | 如何匿名化数据包》
- 另外一个比较特别的地方是
Packet size limit: inferred: 70 bytes - 1518 bytes (range)
,通常来说根据 snaplen 做截断,应该是一个统一的数值,也就是所有的数据包捕获长度应该是一样的,而不是一个范围值,这里是 NPM 回溯分析设备所处理设置的原因。
专家信息如下,有部分协议解析的 Error 问题,以及先前分段未被捕获到、ACK 确认了未被捕获到的分段等 Warning 问题,考虑到 ACKed unseen segment
的现象,更多是包没有捕获到,并不是什么问题。
在业务所提供的故障时间节点 16:45 - 16:48,展开了相关数据包详细信息,如下,会很明显的看到客户端 192.168.0.1 间隔很长时间才会发送数据包。
再增加 TCP 流信息列,可以看到是分属不同的 TCP 数据流(此处和业务应用相关,不做深究),单流之间上下数据包的间隔时间就更多了。
沟通当中,业务又反馈了一次打不开异常,遂向后拉长了数据包捕获时间,根据客户端的源地址进行过滤,同时增加了间隔时间从大到小排序,基本全是大时间间隔。但整体观察规律,一些流中的固定时间间隔(如 60s)更像是 GRPC 调用本身的应用逻辑,貌似不是根本问题所在。
因此基于此阶段的信息,给到研发同事的意见是检查客户端 192.168.0.1 ,因为它在故障时点陷入了沉寂,并无任何数据包发出,疑似问题所在。
研发同事带着问题和建议回去,又和技术厂商沟通了两三天,未能有实质性的原因发现,且同时问题仍在不定时的发生。继又带着疑问而来,说是 DMZ 区域的客户端请求确实发出了,但是服务器端收不到,而且强调了每天故障最开始发生的时间,都是第一次进系统时就会有异常现象,应用上现象显示就是点击页面请求发出去,但是接口一直 pending,错误日志 Connection timed out
。
基于上述现象,又再次取了数据包跟踪文件,从数据包角度来看,在故障时点 11-20 15:09:33 左右,仍然是没有产生任何数据包。考虑到捕获数据包的位置就在客户端所在接入交换机上,客户端一直说发了请求,但是直连交换机在发出去的时候就根本没有看到相关数据包,真是离了大谱,难道直连丢包。。。
交换机上的抓包确实在 15:09:06 - 15:09:33 没有任何数据包,遂坚持之前的结论,检查客户端应用,并要求在故障发生时点在客户端上直接抓包,用来佐证客户端请求是否有发出来。
来了来了,研发带着本地数据包来了,在客户端和服务器两端同时抓包(做了客户端 -> 服务器单方向的过滤),说是在系统故障打不开的时候,很明显看到客户端发了请求,但是服务器没收到。
客户端发方向和服务器端收方向数据包对比如下:
大无语事件,难道真的是啪啪打脸了嘛。。网络交换机丢包?这很不科学,既然有客户端与服务器的数据包这种交互,那么在 NPM 同样回溯分析,是否是同样的现象呢。通过下图 NPM 回溯,发现现象确实一样,同样看到了客户端所发的另一条数据流,可见上层交换机是正常将数据包转发出去了,难道是后面的网络路径中有丢包,这也不可能啊。
此时慢慢理清三个阶段的故障现象以及数据包,得出以下结论:
带着上述疑问,又在 NPM 上往前回溯了一个小时的数据,即 17:00 至故障时间点 18:05 的数据包,发现了一个重要的现象,在如此长的时间内,该数据流空空如也,没有任何数据包交互,仅是在故障时间节点客户端单方向产生了 0xc05c - 0xc063 几个数据包,毫无响应后 FIN 结束连接。
至此我突然明白了问题所在,我一直忽略掉了一个关键环节,防火墙。在想到防火墙的时候,又回顾了整个排障过程,最终定位到了原因,综合整理如下:
因防火墙并不在网络组维护,后转至了安全组处理,之后了解到在防火墙上针对该应用 IP 通讯对单独调整了空闲会话时间限制(默认为一小时),至此业务系统恢复正常。