服务器日常工作中,经常出现某个进程cpu占用过高疯狂报警,导致服务器挂掉,这时候除了重启服务器和回滚,还需要定位到问题出现并解决.
(因为没有现成故障图可以分享,所以截取一下网上的图进行分析)
1.查看故障进程
直接进入服务器,输入top命令,可以看到PID为1878的进程cpu占用达到200%,cpu的最高占用率等于服务器的cpu核数,比如四核,所有cpu占用率加起来不超过400%.一个进程的cpu占用率频繁超过100%,基本说明该进程运行有异常.
知道了故障进程的PID后,输入ps -ef|grep 1878,查看该进程的名称,位置及相关信息.
2.排查问题
输入命令jstack -l 1878 >>1878堆栈日志.log,可以得到一份1878进程的java堆栈日志.jstack是java虚拟机自带的一种堆栈跟踪工具,-l可以不加,加了会打印锁的附近信息.
接着输入top -Hp 1878命令,可以查看该进程的线程信息.
通过图可以看到pid为8721和8075的线程各占用了100%的cpu.这还有一个问题,jstack导出的日志中pid是以十六进制的形式保存,所以通过命令printf "%x\n" 8721,得到TID2211.
接下来就很简单了,输入命令grep 2211 -A20 1878堆栈日志.log,可以查到PID8721进程的堆栈信息,可以看到线程处于runnable状态.可以多导出几次日志,会发现该线程一直无法停止.
3.解决问题
发现故障线程后,就需要通过堆栈日志,定位到具体的代码.这里的问题是在jdk8.0版本以下,高并发环境下使用hashmap会出现死循环,出现cpu占有率100%.解决方法就是改为使用concurrentHashMap.