排查一个线上网络超时问题的记录

492 阅读4分钟

问题描述

某天,线上突然有个接口报了大量的网络超时的报警,且这个报警是没有规律的

问题排查过程

  1. 首先排查是不是网络抖动的问题,但是这台服务器上,除了这个接口超时报警,其余接口都是正常的,所以排除这个原因
  2. 排查是否是因为下游是个慢接口,导致某些查询条件比较耗时,从而网络超时,但是和下游的同事联系之后,他们的监控显示他们的接口响应都非常快,且没有任何抖动
  3. 查看代码,发现这个接口向公司内部其他部门发起了一个http请求,而不是走的rpc,于是怀疑是http的过程出了问题

一次http请求的全过程如下:

sequenceDiagram
    participant Client as 客户端
    participant DNS as DNS服务器
    participant Server as Web服务器

    Client->>DNS: 解析URL,发起域名查询(如www.example.com)
    DNS-->>Client: 返回域名对应的IP地址
    Client->>Server: 发起TCP三次握手建立连接
    Server-->>Client: 确认,完成TCP连接建立
    Client->>Server: 发送HTTP请求(包含请求行、请求头、请求体等)
    Server->>Server: 处理请求(根据请求获取静态/动态资源)
    Server-->>Client: 发送HTTP响应(包含响应行、响应头、响应体)
    Client-->>Server: 根据响应头判断,接收并处理响应内容
    Client->>Server: 发起TCP四次挥手关闭连接
    Server-->>Client: 确认关闭,连接关闭

4.上游的监控反应他们的接口都是正常的,没有超时的请求记录,那么就说明,我们的http响应超时,不是数据传输超时,而是连接超时,而http连接分为了两个大的部分,一个是域名解析,另一个是三次握手建立连接,刚才说了,除了这个接口,其余的rpc请求都没有出现抖动或者超时,那说明网络肯定是没有问题的,那么问题大概率不会出现在三次握手建立连接这儿的丢包上,而大概率是出现在了域名解析这一问题上

验证猜测

  1. 到服务器上使用tcpdump进行抓包,在服务器上执行如下命令:

不知道tcpdump命令怎么用的,请参考我的另一篇文章:Linux必须要掌握的常用网络命令

sudo tcpdump -i enp5s0 -n -w capture.pcap # enp5s0是网卡的名字  capture.pcap是抓包结果保存的文件

2. 当服务器再次出现超时报警的时候,停止抓包,并将抓取的文件capture.pcap下载下来

一般不要抓太长的时间,否则太大的数据包,根本看不过来,尽量5~10分钟就已经差不多了

  • 使用Wireshark打开这个文件,输入过滤条件

    例如,我这里有问题的http请求是https://example.com/get_info?x=1&y=2

    那么过滤条件输入 dns && _ws.col.info contains "example.com",如图:

image.png

  1. 经过查找,果然发现其中有一次dns解析的upd请求,没有数据包返回

这里数据包里包含了一些公司的信息,我就不放出来了

归因

根据上面的排查,我们总算知道了是因为某次dns解析没有返回结果,导致了超时,那么很明显是dns域名解析服务器有抖动了,来看看我们的dns域名服务器地址是什么。

执行 cat /etc/resolv.conf 查看,结果如下:

# Generated by NetworkManager
nameserver 10.27.248.120
nameserver 10.27.244.88

于是,我们来验证一下从这个域名服务器解析域名大概多少时间会出现一次超时,使用如下命令:

执行下面的命令,一旦在不停打印DNS解析结果的时候,出现了明显的卡顿(1s左右),那就说明dns解析有明显的抖动,那就该找你们公司的负责DNS服务器的同事解决这个问题了,一般加个几台域名解析服务器就能解决问题了

while :;do time nslookup example.com 10.27.248.120;done

命令整体结构及含义

  • while :; do... done 这是一个无限循环的结构。在 bash 等 shell 脚本环境中,while 用于循环控制,这里 while 的条件部分是 :(冒号在 shell 中表示恒为真的条件),意味着这个循环会一直持续执行下去,直到通过其他方式(比如手动按 Ctrl + C 等中断操作)来终止它。
  • time 命令是用于统计其后面所跟命令执行时消耗的时间情况,包括实际执行时间、用户态 CPU 时间、内核态 CPU 时间等信息。
  • nslookup 是用于查询域名对应的 IP 地址等 DNS 相关信息的工具。在这里执行 nslookup example.com 10.27.248.120,意思是使用 10.27.248.120 这个 DNS 服务器去查询 example.com 的域名解析信息。

执行效果

当运行这条命令后,会不停地使用 10.27.248.120 这个 DNS 服务器来查询 example.com 的域名解析情况,并且每次执行 nslookup 操作时,都会通过 time 命令统计并输出该次查询操作所花费的时间信息,屏幕上会不断滚动显示类似下面这样的内容(示例,实际时间数值会根据网络等情况变化):

Server:         10.27.248.120
Address:        10.27.248.120#53

Non-authoritative answer:
Name:   example.com
Address: 39.156.66.10
Name:   example.com
Address: 220.181.38.148

real    0m0.032s
user    0m0.000s
sys     0m0.004s

需要注意的是,如果长时间持续运行这样的无限循环命令,可能会对所使用的 DNS 服务器造成一定的查询压力,并且在命令行界面会不断输出大量信息,要合理使用并适时终止它(通过 Ctrl + C 等常规中断手段)。 同时,如果所在网络环境对外部 DNS 服务器访问有限制等情况,可能还会出现查询失败等问题。