java应用的服务器cpu问题排查思路
cpu过高时,基本思路是:
查看cpu高的进程id->获得线程id->查看线程的执行栈 ;
一,进程
1 | top |
然后P
(大写),会按照CPU排序
得到如下结果:
可以看到pid20469
这个进程的cpu占比非常高
二,获得线程id
1 | ps -mp 20469 -o THREAD,tid,time |
如图,可以看到tid20493
这个线程的cpu占比达到了99.5
三,分析
3.1 工具环境
查看java的执行栈需要用到jstack,确保你的linux安装了jdk-devel套件
1 | yum list --showduplicate | grep java-11 | grep devel |
根据输出结果进行安装
1 | sudo yum install java-11-openjdk-devel.x86_64 |
3.2 翻译线程ID
1 | printf "%x\n" 20493 |
输出500d
3.3 得到堆栈
1 | jstack 20469 |grep 500d -A 60 |
传入pid
和翻译的线程id500d
得到堆栈结果:
四,测试代码
1 | public class Main { |
这里启动了2个线程,都是死循环,但是第2个线程会sleep2秒。
死循环本身的cpu占用不高,占用高的原因是死循环里的System.out.println
,这个方法会不断通过IO流输出数据。
将代码copy到服务器,新建Main.java
,并直接通过执行
1 | java Main.java |
但是由于你通过ssh
连接的服务器,System.out.println
的结果也同时输出到终端上,这个结果是通过sshd
服务回传到你的ssh
窗口上,此时你在看top
的进程时,也会看到sshd
进程的cpu也很高,所以这里执行java
的方法,最好通过nohup
:
1 | nohup java Main.java |