导出jstack和内存信息,重启系统,尽快保证可用性。
主要原因(可导致不可用):
(1)读数据量较大,内存耗尽,Full GC多,慢; (2)耗CPU操作,CPU过高,慢;
原因(只慢,还可用):
(3)阻塞,耗时,出现随机;(4)线程WAITING,整体不可用,但无法复现;(5)多个线程死锁
这种要查看系统日志,查CPU和系统内存,看不出具体问题,阻塞性操作,CPU和系统内存使用都不高。
一. Full GC次数过多
两个特征:CPU超过100%,jstack命令看,主要是垃圾回收线程
jstat命令看监控GC情况,Full GC不断增加。
操作概要:看CPU,看进程(线程),看内存日志(哪些对象多),内存占用不高,Full GC多,System.gc()禁用
1、输入 “top” 看CPU高示例:
2、来查看哪些线程CPU高top -Hp 9:
进程9中各个线程CPU占用情况,jstack命令看10线程为什么耗费CPU最高。jsatck中线程id都转换成十六进制。查看转换结果:root@a39de7e7934b:/# printf "%x\n" 10a (结果说明在jstack中的展现形式为0xa),jstack命令:
nid=0xa,nid是系统线程。VM Thread是垃圾回收线程。GC停顿时间长,慢。GC情况:
3、Full GC数量高达6793,不断增长。dump内存日志(看是否是内存溢出),通过eclipse的mat看,展示对象树结构:
PrintStream最多,消耗量只有12.2%。不足导致大量Full GC,显示System.gc()调用导致GC次数过多,解决:添加-XX:+DisableExplicitGC禁用
Shallow Size:对象本身占内存大小,不包含引用对象。1)对象(非数组)Shallow Size由其成员变量的数量和类型来定,2)数组ShallowSize由数组类型和长度决定,为数组元素大小总和
Retained Size=当前对象+直/间接引用到对象大小总和。(A->B->C,C间接引用) ,排除被GC Roots直/间接引用对象。就是当前对象被GC后,Heap释放掉的总内存
二、CPU过高
jstack得到线程信息,类似VM Thread线程(上面),如代码耗时计算,得到线程堆栈信息:定位UserController34行
三、接口不定期耗时
消耗CPU和内存都不多,jstack命令信息没法判断
思路:压测接口,复现堆栈日志:阻塞在18行
四、 线程WAITING
罕见情况,“不可复现性”,用CountDownLatch时,并行任务完成,唤醒主线程。一个连接一直等待服务器响应。其余WAITING。
问题线程与其他一样,思路:grep在jstack日志,找所有TIMED_WAITING线程,导出到a1.log:
10s后,再对jstack日志grep,导出到a2.log:
重复2,导出3~4文件对比,几个文件一直存在的用户线程,是问题线程。正常线程不会20~30s后还等待。通过线程名,排除框架线程
看堆栈信息,哪个代码导致:Thread-0是线程,SyncTask8行导致
五、 死锁
jstack检查死锁,日志中打印:
六. 小结
(1)top看CPU情况,top -Hp <pid>看线程,将线程id转换为十六进制,jstack日志:
1、VM Thread,jstat -gcutil <pid> <period> <times>监控GC状,jmap dump:format=b,file=<filepath> <pid>内存数据。放到eclipse的mat工具分析
2、正常线程,堆栈信息看哪处代码消耗CPU;
(2)CPU、内存都不高:
压测,jstack看堆栈信息;
无法复现,多次导出jstack日志,找出问题线程。
jstack看死锁