前文
之前有发布一篇文章,讲述curl后服务端返回rst的一种解决方案,详细:https://blog.csdn.net/weixin_42681866/article/details/123262531,当时通过抓包,分析到了是中间设备拦截导致请求未到服务端。
但本次不同,主要是偶发异常,上百次里有那么1-2次服务端无返回;另外是涉及到服务端的请求,所以无响应要分析服务日志才行。
分析
因为极度偶发,所以在日志定位上很困难。通过解析时间段的服务端日志,发现并没有异常返回,http码都是200;那么此时怀疑是中间设备拦截了,需要进一步地抓包分析。
同样的,在客户端和服务端同时抓包:
# 客户端抓包,指定网卡,不指定ip
tcpdump -i eth0 -w ./target.cap
# 服务端抓包,指定网卡,指定ip(因为太多客户端)
tcpdump -i eth0 host xxx.xxx.xxx.xxx and port 80 -w ./target.cap
然后写个循环curl脚本,批量来触发偶现时间,批量脚本script.sh:
#!/bin/bash
for i in $(seq 1 100)
do
curl -s -X GET http://xxx.xxx.xxx?index=$i;
echo "------------------------------------,当前位于:$i"
done
通过观察curl的结果,如果没有返回正常值则判断本次循环里出现了问题,此时将包放入wireshark进行分析。
解决
根据打印的日志(当前位于),定位到第几次,然后进入wireshark进行搜索(相关搜索规则可以自行搜索),我这里简单用http.response.uri和http.request.uri来进行匹配请求和返回的http情况,比如:
http.response.uri matches "http://xxx.xxx.xxx" || http.request.uri matches "http://xxx.xxx.xxx"
经过分析,比如我们丢失了10号请求,结果在客户端没有抓到发送的包,在服务端没有抓到接收的包。所以本次不是在中间设备被拦截,而是客户端压根没发送到该网卡。
结果:确认了客户端并不是多网卡机器,所以不存在发送到其他网卡的情况;而本事件是偶发,所以底层内核的发包也是正常的;最后定位到是dns的问题,当负载过高,导致内网dns出现异常,进而导致域名没有请求到对应的服务器ip上,所以没有发送对应的包。
解决:可以通过换个dns或者指定hosts的形式临时解决。