问题:
上周开始公司托管在IDC机房的一台服务器频繁掉线,导致ssh连接不上,过几分钟又恢复。通过监控查看,没有什么有价值的结果,因为是对公网IP监控的,当时监控是没有数据的,唯一有价值的就是通过监控的No data 时间来看,是不定时触发的,排除了因某些定时任务导致。
过程:
0. 询问机房人员调取监控图
监控排查无果后,果断询问机房人员,调取问题发生的时间段流量监控,发现交换机的入口流量已经超过了100M(百兆交换)导致流量骤增,公网无法访问。 机房那边的的入流量徒增也就是我们服务器这边的出流量,猜测有大量上传操作或者cpu飙升的现象。
1. 排查机器存活
ssh连接不上我们先要确定是 机器确实宕机了 还是 ssh断掉了 还是公网IP无法连接了 ?
问题再次出现时,通过托管在机房的集群环境中其他机器,用内网IP尝试登陆,成功! 机器是存活的,ssh服务也没有挂!所以就是结合前面的结果,问题就在带宽流量打满了,无法连接。
2. 排查机器CPU,内存情况
登录上去以后,top命令 C , 果断找到"罪魁祸首"
image.png
根据PID,找到程序父ID,直接定位是哪个进程引起的
ps -ef|grep id
lQLPDhsMT0YWYM7NAkvNCNuwCHsyCFyYcdUB5NdiSYC-AA_2267_587.png
3.找到“涉事”进程
根据公司业务逻辑java程序都以容器的方式运行,并且可以看到运行信息带有env为prod的字样,用docker ps 找出这个容器
user@ubuntu:/home1/ALG/identification/upload$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ea271034d32b harbor.hw.xxxx.com:5000/health-cloud-server/health-cloud-ai-manager:883e2fc9-prod "/bin/sh -c 'java -D…" 11 days ago Up 11 days 0.0.0.0:8004->9000/tcp health-cloud-ai-manager-prod_health-cloud-ai-manager_1
8f6accb9cd0c harbor.hw.xxx.com:5000/health-cloud-server/health-cloud-ai-manager:c9a69dcb-k8s-dev "/bin/sh -c 'java -D…" 2 weeks ago Up 2 weeks 0.0.0.0:8001->9000/tcp health-cloud-ai-manager-dev_health-cloud-ai-manager_1
4.进入容器排查(容器ID-ea271034d32b)
ss命令看soket连接情况
root@ea271034d32b:/# ss
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
u_str ESTAB 0 0 * 694692659 * 0
u_str ESTAB 0 0 * 694686601 * 0
udp ESTAB 0 0 172.24.0.2:48273 8.8.8.8:domain
udp ESTAB 0 0 172.24.0.2:60631 202.106.0.20:domain
tcp ESTAB 0 285 172.24.0.2:46840 121.36.25.185:8635
tcp SYN-SENT 0 1 172.24.0.2:39208 124.70.70.103:8635
tcp SYN-SENT 0 1 172.24.0.2:47412 121.36.25.185:8635
tcp CLOSE-WAIT 0 0 172.24.0.2:44428 119.3.214.140:8848
tcp SYN-SENT 0 1 172.24.0.2:47386 121.36.25.185:8635
tcp ESTAB 0 36844 172.24.0.2:35628 216.118.240.74:http-alt
tcp CLOSE-WAIT 1 0 172.24.0.2:48802 119.3.214.140:8848
tcp ESTAB 0 33184 172.24.0.2:35634 216.118.240.74:http-alt
tcp SYN-SENT 0 1 172.24.0.2:39218 124.70.70.103:8635
tcp SYN-SENT 0 1 172.24.0.2:33382 119.3.214.140:8848
tcp ESTAB 0 484 172.24.0.2:33378 119.3.214.140:8848
tcp ESTAB 0 285 172.24.0.2:38096 124.70.70.103:8635
tcp SYN-SENT 0 1 172.24.0.2:52370 216.118.240.74:http-alt
tcp CLOSE-WAIT 1 0 172.24.0.2:37550 119.3.214.140:8848
tcp ESTAB 0 0 172.24.0.2:43842 119.3.221.159:8501
结果上看有两处 ESTAB状态时,Send-Q 堆积过多,这肯定是不正常的
tcp ESTAB 0 36844 172.24.0.2:35628 216.118.240.74:http-alt
这个客户端IP也比较可疑,来自香港,因为这个服务只是公司内部调用 ,集群机器也没有香港的机器。
5. 询问相关业务人员,是否可以重启
当务之急的解决办法最快清除这些堆积的包与链接,就是重启容器,询问相关业务人员,进行了重启后,再次查看CPU状态已经恢复正常,通过公网IP也可以立刻链接上了,目前需要多观察几天,是否还会复发。
总结:
1.recv-Q 表示网络接收队列
表示收到的数据已经在本地接收缓冲,但是还有多少没有被进程取走,recv()
如果接收队列Recv-Q一直处于阻塞状态,可能是遭受了拒绝服务 denial-of-service 攻击。
2.send-Q 表示网络发送队列
对方没有收到的数据或者说没有Ack的,还是本地缓冲区.
如果发送队列Send-Q不能很快的清零,可能是有应用向外发送数据包过快,或者是对方接收数据包不够快。
从图中可以看到是大量的 send-Q ,可以判定是发送数据给目的地址的时候出现了阻塞的问题,导致了包堆积在本地缓存中,不能成功发出去。那么问题就产生在了客户端, 重启了容器,清掉正发送的队列,再次观察。
3.关于ss 命令和 netstat 命令都是排查网络连接的利器,Recv-Q ,Send-Q的值是如何进行分析的呢?
一. Established状态时:
- Recv-Q:"OS持有的,尚未交付给应用的 数据的 【字节数】"
- Send-Q:"已经发送给对端应用,但对端应用尚未ack(确认)的【字节数】。此时,这些数据依然要由OS持有"
二. Listen状态时:
- Recv-Q:"服务端已经接收到的,但尚未交付给应用的【 tcp连接的数量】"
(客户端通过 connect() 去连接正在 listen() 的服务端时,这些连接会一直处于这个 queue 里面直到被服务端 accept()调用派给应用) - Send-Q:listen时,backlog的大小,其值为min(backlog, somaxconn),简单理解为在等待区等待的【连接数】最大值
补充
包括在tomcat调优时会有accept-count ,max-connections 参数
- max-connections : 允许的最大连接数
- accept-count : 当超过最大连接数后,将超额的连接放入accept()队列中,等待前面空闲后,os从这里面调用正在等待的连接,如果accept满了,将不会接受任何请求,也就是可能会给客户端返回502,这个accept-count值就是在除了最大连接数,还可以在额外多接受几个连接。
参考:
https://www.cnblogs.com/leezhxing/p/5329786.html
https://blog.csdn.net/yjh314/article/details/51038774
网友评论