早上一起来,服务cpu跌低了。
登录机器,排查问题方法:
1.执行命令 top (查看cpu占比比较大的进程pid),
2.执行 top -Hp pid (查看对应进程 下面cpu占比比较大的 线程id(就是对应的pid))
3. 用 printf "%x\n" (第2步找到的线程id) 转换成16进制的,应为线程id 在堆栈中有一个对应的16进制的nid
4.执行 jstack pid | grep 'nid(步骤3中的nid)' -A 20 查看对应的线程的堆栈信息。
补充 jstack 命令:
2.网络排查
netstat -antop 显示tcp的网络连接信息
- -a或--all 显示所有连线中的Socket。
- -n或--numeric 直接使用IP地址,而不通过域名服务器。
- -t或--tcp 显示TCP传输协议的连线状况。
- -o或--timers 显示计时器。
- -p或--programs 显示正在使用Socket的程序进程pid和程序名称。
显示的两个参数信息recv-Q send-Q ,两个值通常应该为0,如果不为0可能是有问题的。packets在两个队列里都不应该有堆积状态。可接受短暂的非0情况
recv-Q 表示网络接收队列
表示收到的数据已经在本地接收缓冲,但是还有多少没有被进程取走,recv()
如果接收队列Recv-Q一直处于阻塞状态,可能是遭受了拒绝服务 denial-of-service 攻击。
send-Q 表示网路发送队列
对方没有收到的数据或者说没有Ack的,还是本地缓冲区.
如果发送队列Send-Q不能很快的清零,可能是有应用向外发送数据包过快,或者是对方接收数据包不够快。
ss -ltn 显示tcp的全连接 和 半连接数
-l 显示处于监听状态的套接字
-t 显示tcp网络连接
-n 不解析服务名称,已数字方式显示
<1> 当socket是listen 状态(eg: ss -lnt)
Recv-Q: 全连接队列的大小,也就是当前已完成三次握手并等待服务端 accept() 的 TCP 连接
Send-Q: 全连接最大队列长度
<2> 当socket 是非listen 状态(eg: ss -nt)
Recv-Q: 未被应用进程读取的字节数;
Send-Q: 已发送但未收到确认的字节数;
3.排查线程死锁。
jps 是java提供的一个显示当前所有java进程pid的命令.
1 通过jps 找到进程
2. jstack pid(进程号) 然后查看 堆栈日志中的deadlock关键字
TCP 全连接队列的最大值取决于 somaxconn 和 backlog 之间的最小值,也就是 min(somaxconn, backlog), linux 的默认大小是128。
somaxconn
是 Linux 内核的参数,默认值是 128,可以通过/proc/sys/net/core/somaxconn
来设置其值;backlog
是listen(int sockfd, int backlog)
函数中的 backlog 大小,Nginx 默认值是 511,可以通过修改配置文件设置其长度;
tcp_abort_on_overflow 共有两个值分别是 0 和 1,其分别表示:
- 0 :如果全连接队列满了,那么 server 扔掉 client 发过来的 ack ;
- 1 :如果全连接队列满了,server 发送一个
reset
包给 client,表示废掉这个握手过程和这个连接;
如果持续不断地有连接因为 TCP 全连接队列溢出被丢弃,就应该调大 backlog 以及 somaxconn 参数。
tcp全连接溢出统计命令查看: netstat -s | grep "overflowed"
tcp半连接溢出统计命令:netstat -s | grep "SYNs to LISTEN",
tcp半连接大小查看: