问题描述
在某一天系统更新上线一个版本后,运维人员通过监控发现服务器出现cpu使用率超过200%的问题,导致监控系统频繁告警。
排查过程
我们的tomcat是部署在linux环境中,下面的排查过程均在linux下进行。
1. 查看后台服务
通过查看tomcat的后台日志,发现日志正常打印,未发现异常信息。
2. 查看服务器信息
2.1 找出耗cpu的进程
使用top命令查看特定用户(user1)的内存、cpu及各进程的信息:
[root@localhost ~]# top -u user1
使用上面的命令,可以看到下面的信息:
从上图可以看到存在一个java的进程cpu使用率很高,超过了200%的数值。
ps:从图中可以看到pid为150252(pid即为java进程id),用户为user1,%cpu、%mem分别表示cpu、内存的使用率
2.2 确认进程信息
[user1@localhost ~]$ jps -m # 使用jps命令可以快速找到java进程的pid
[user1@localhost ~]$ ps -fu user1 | grep tomcat # 使用ps指令可以找到pid为150252为tomcat进程
通过上面使用top命令找到了cpu使用率过高的进程,通过jps可以确认是tomcat进程。
2.3 找出耗cpu的线程
1)找到耗用最高的线程和占用cpu的时间
[user1@localhost ~]$ ps -mp pid -o thread,tid,time
或者
[user1@localhost ~]$ top -hp pid
pid即2.1中找到的进程id(150252),上图指令就是为了找出该进程下的线程信息。如下图:
ps:上图中的pid是线程id,找到%cpu使用率较高的线程逐一分析。
2)把该线程id转化为16进制
[user1@localhost ~]$ printf "%x\n" tid #将线程的tid转换成十六进制
3)从jvm堆栈中查找线程信息
在第2步中找到了耗时较高的线程id,下面通过jvm的堆栈信息找到线程信息,使用下面的命令可以获得jvm的堆栈信息:
[user1@localhost ~]$ jstack pid | grep tid -a100
这里的pid代表的是tomcat进程id,tid是16进制表示的线程id,线程堆栈信息如下:
从上面可以看到是一些线程信息,通过上图红框中的状态为runnable的线程信息,即为正在运行的线程,从这里可以找到相关的信息,接下来就是分析你的代码,这里是因为代码中使用了类似于while死循环导致的。
总结
cpu使用率过高的原因,大概有以下几种情况:
1、java 内存不够或溢出导致gc overhead问题,gc overhead 导致的cpu 100%问题;
2、死循环问题,如常见的hashmap被多个线程并发使用导致的死循环 或者 死循环代码;
3、某些操作一直占用cpu
大多数都是因为线程无法终止或出现死循环等原因,但是仍然需要根据实际情况,具体问题具体分析。