一、现象

公司内员工通过域名(https://)访问我们自己后台管理系统,出现无法访问的情况;但是并不是一直无法访问,只是偶尔会出现,出现之后持续的时间也不确定,长则十几二十分钟,短则一两分钟;
后台管理系统已经部署使用很长时间了,这个时候发生无法访问的情况,实属不该;
image

二、架构简介

后台管理系统部署机房服务器上,机房和公司不在一起;
通过nginx代理后端的3台服务器,实现负载均衡;
访问流程图:
image-1664411293929

三、排查过程

由于【无法访问】的情况出现时间并不确定,所以排查时间大都耗在了等待复现上;

1、排查过程一:

当【无法访问】的情况复现时,
1、首先确认了服务器的状态:cpu、mem、load、io,都是正常的;
2、外网其他用户可以正常访问;(我们用手机流量访问服务,其他异地公司的同事也协助测试访问,显示正常)
3、查看nginx日志,往后端的分发和处理均正常;(但是通过过滤日志发现,nginx当时并没有收到来自公司的请求;)
4、考虑到可能是并发增多,触发了访问频率拦截限制之类的配置,于是注释了nginx.conf 上的访问频率限制,并关闭了两端防火墙上的安全拦截配置;(事实证明,并没有效果)
5、排查了机房的带宽;(带宽并没有跑满)

排查结果:通过上述动作判断,外网客户访问并无异常,主要发生在公司内网部分用户上(内网用户没有规律)。且nginx并没有接收到用户的请求,可能是公司防火墙没有发出请求,也可能是机房防火墙拒绝了请求,再或者是请求到达nginx服务器后,被服务器拦截、丢弃、拒绝等,总之,请求没有到nginx,更别说处理请求了;

2、排查过程二:

当问题复现时,进行了抓包,目的是先确认客户端发送的请求是否到达了服务器;
公司防火墙过滤会话:
已经发送出了报文
image-1664411356899
机房防火墙过滤会话:
已经接收到了报文
image-1664411372557
但是他们的会话剩余时间比其他的会话短了很多,只有几秒钟;
于是在nginx服务器端进行了抓包(用tcpdump抓包保存,下载保存的文件用wireshark分析)
image-1664411384482
发现客户端和nginx服务端建立TCP时,服务端没有回应 SYN+ACK 报文,也就是不相应客户端的SYN报文?!

再在PC客户端上过滤:
image-1664411397310
发现都是 SYN_SENT 状态,也就是客户端发送了SYN报文,在等待服务端响应;
到此,故障定位已经明确了;

四、故障原因

TCP握手无法建立,nginx服务器对客户端的SYN报文不做响应;
最直接的办法,上网搜;
果然,网上找了很多类似的问题,还有不少和我们的情况基本一样;
都指向了这两个linux内核参数:tcp_timestamps 和 tcp_tw_recycle
这里就不介绍参数含义了,网上多得是,自己搜,或者看下面的【参考链接】;
或者可以通过netstat过滤被系统丢弃的包,可以看到这个数量是递增的,也验证了系统确实丢弃了报文;
image-1664411419907

五、问题解决

编辑 /etc/sysctl.conf:

net.ipv4.tcp_tw_recycle = 0

1是开启,0是关闭;

退出后执行 sysctl -p 生效;

这样可能会导致 TIME_WAIT 状态的连接增多;因为 tcp_tw_recycle 参数就是为了回收TIME_WAIT 状态的链接的;
不要修改 net.ipv4.tcp_timestamps !保持默认即可,因为 tcp_tw_recycle 开启是需要依赖 tcp_timestamps 的;tcp_timestamps 关闭了,tcp_tw_recycle 开启也不生效;

重点:不要修改 tcp_timestamps 参数值,该值默认为1(开启状态),因为有许多其他内核参数是依赖于它的,如果关闭,会导致其他一些内核参数不生效,极有可能造成系统故障;

参考链接

https://blog.csdn.net/zhuyiquan/article/details/68925707
https://blog.csdn.net/qq_25518029/article/details/120139267
https://blog.csdn.net/jueshengtianya/article/details/52130667
https://blog.csdn.net/chenlycly/article/details/80369408
https://blog.huoding.com/2012/01/19/142
https://www.cnblogs.com/larry-luo/p/15649168.html

附录一

实际排查过程的经历并没有这么简单,从故障发现到解决经历了很长时间,基本快有一个月了;
首先,这个后台管理系统基本都是其他部门的人在用,虽然是我们部门开发的,但是并不经常使用,导致发现问题并不及时,即便其他部门的人发现了无法访问,多数情况下也会以为是网络问题造成的(因为那期间,运营商的网络经常出故障,导致即便是我们不敢相信网络是稳定的);
其次,问题复现很难,因为要找到问题发生时,具体有何现象,公司内哪些人不能访问(因为之前有人因为dns的问题导致部分人不能上网)?外网客户是否还能访问?等等…并且复现时,很难抓住机会,有时候就一两秒的事儿,刷新一下网页就又好了;
之后,在抓住多次复现的机会后,各种排查对比,发现并没有规律,一时陷入困惑;
最后,才想到用最直接、简单的办法:从头到尾的抓包,沿途进行排查;结果第一波的TCP链接排查就把问题定位了;后来在网上一搜,才发现有这么多的案例,并且和我们的情况还极度相似;
并且处理问题过程中,由于误操作,导致系统宕机了 -_-||,所以在【问题解决】的结尾标明不要动 tcp_timestamps 参数的(发现网上竟然还有人说要关闭 tcp_timestamps 参数,如果你信,你就改!)。
有条件的话可以在测试环境先模拟,再修改参数。即便我们这次通过修改 tcp_tw_recycle 参数值解决了问题,你也不要上来就改,多查、多测、多试…好了,不说了,说多了,也累了,爱J8听不听;

附录二

另,附上宕机前的操作:
编辑 /etc/sysctl.conf,添加了以下内核参数:

net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_timestamps = 0

1是开启,0是关闭;

退出后执行 sysctl -p 生效;
之后出现了大量的丢包重传,并且重传的包也一直超时;
表现为,在nginx日志中看到接收到的请求,被分发到后端服务器,但是一直没有响应,最终显示超时连接;
这是 nginx error.log 中的部分日志:
image-1664411605557
通过tsar查看系统TCP,可以看到从14:22开始,重传率就上升起来了;
image-1664411615886

打赏
支付宝 微信
下一篇