一: 问题背景与现象
1、健康检查失败
2、接口测试反应慢
3、系统多次CPU或内存使用率飙升,且是java进程引起
二: 解决问题思路
1.确定服务已部署成功且没有被回收,健康状态检查成功,打开终端控制面板,登录服务器,若不能直接登录则先登录跳板机,再登录服务器,执行jps命令查看服务进程是否还存在
2.执行top命令查看CPU和内存使用率。若发现有一或多个CPU或内存的使用率居高不下(例如80%~100%),且是Java相关进程引起的,若不是则排查其他问题,如系统问题。q退出top,top使用详解
3.执行top -Hp ${pid} (步骤2中cpu或内存使用率过高的Java进程号)。若是接口反应慢问题,则可在此时请求接口,观察得到持续占用CPU或内存使用率过高的线程号(用于后续步骤5)。
3.1、若cpu使用率过高,执行jstack ${pid} > jstack.log (步骤2中pid进程号)。得到该Java进程的线程快照jstack.log。
3.1.1、执行less jstack.log ,将之前有问题的(步骤3中)线程号转换为16进制,在线程快照中查找到该线程,输入: /16进制线程号 enter ,查看其线程相关信息,
查找与本服务密切相关的信息(如自定义类),确定问题所在行,解决问题,重试。
若发现是JVM的垃圾回收线程。再搜索整个文件,没有被死锁的线程。于是怀疑内存没有正确释放,JAVA进程已使用的内存,已经达到了分配给JVM的最大内存。导致垃圾回收频 繁执行FullGC,占用了CPU。
执行jstat -gcutil ${pid} 若发现年轻代,老年代内存使用率太高。进一步证实之前的怀疑。jstat使用详解
3.2、若内存使用率过高,执行jmap -histo:live ${pid} | head -10 ,若还不能确定造成内存泄漏的类, 则执行jmap -dump:format=b,file=${dumpFileName} ${pid} 得到当前内存快照。jmap使用详解
4. 使用eclipse的memory analyzer导入内存快照,进行分析。找出内存异常的对象。
5. 修改程序的BUG。
6. BUG修复以后,继续定时获取内存快照,持续观察。直到彻底解决问题。
三、 解决问题的实践过程
登录跳板机,再登录服务器,例如:
$ ssh [email protected]
password: xxxx
$ ssh 10.247.3x.xx
(3) top 命令查看 %cpu %mem (正常状态)
(4) 测试接口复现问题 确定消耗资源较大的进程 pid
测试接口:http://hostxx/nxschema/api/v1/type/mysql/catalog/plus_table_test/entity/T_MailInfo
此时top:可以看出pid为4083的进程占用cpu资源较大
(5) top -H -p 4083 找出进程4083中消耗资源最大的线程pid 第一条记录pid为21181
(6) 将进程4083的所以线程信息存入jstack.txt 查看与线程21181相关的信息
jstack -l 4083 > jstack.txt
less jstack.txt
/52bd (将pid 21181转换为16进制52bd)
查看记录中与本线程52bd有关的记录 确认问题所在行