前不久生产服务器出现周末活跃用户增加时,应用占满CPU的情况,记录一下我的处理过程。
1、首先top查看各进程的资源使用情况(图是事后截的,当时java的CPU占用达到700%)
2、发现JAVA占用很高,于是使用 top -H -p 1126(java进程pid),查看到底是哪个线程占用cpu。当时的情况是有好几个线程占用CPU达到99%,记下其中一两个pid。 printf %x 24813将这个pid转成16进制。
3、打印堆栈信息 jstack -l 1126(JAVA进程pid) > ps.txt ,这样我们就得到了ps.txt文件,存有我们需要的信息。
4、使用16进制的线程pid去堆栈里搜索,当时的线程pid是3858,如下图,可以看到原来是GC线程占满了CPU,这里可以猜测是代码产生了过多的对象,一直需要垃圾回收。(当时应该再看看GC情况,就可以更加有力的应征,不过当时我着急着恢复应用,就没有看)
查看GC情况可以使用jstat -gc 1126 5000 每个5秒打印GC情况
5、往前查看堆栈,在发生垃圾回收前主要是elasticsearch线程处于RUNNABLE
6、结合自己的应用情况,这是最近加进来的为了优化搜索用的,elasticsearch线程在跑doSelect方法。最后定位到垃圾代码,这里每次去Elasticsearch搜索1W个对象。当初设计是认为这个对象只有id和text,应该很小,垃圾回收没问题。但是当用户量大,频繁访问就很成问题。
7、最后修改成按需取,如果需要排序要在elasticsearch加字段再进行排序。
8、上线,然后周末用户量变大,没有再出现CPU突然跑满得情况,问题解决。