赞
踩
当系统出现卡顿或者应用程序的响应速度非常慢,就可能要考虑到服务器上排查一番,以下是我常用的排查流程:
1、top
:观察占用CPU或者MEN(内存)使用情况最高的进程,记录PID;
TIP:
(1)、“1” 显示出多个逻辑CPU使用情况;
(2)、“X” 高亮显示CPU列,并排序,"Z"红色展示;
(3)、“shift + <” 或者 “shift + >” 变更高亮的列;
(4)、“F”配合 “空格”指定需要展示的列;
(5)、“S”设置刷新的间隔时间;
2、top -p PID
:观察该PID对应进程的占用情况。“shift + h” 开启线程显示,观察CPU占用较高的线程有哪些,记录对应TID;
3、printf "%x\n" TID
:将线程对应PID转为 16进制数(TID16);
4、jstack PID | grep -A 30 "nid=0x + TID16"
:查看该线程的堆栈信息;
5、通过线程的堆栈信息,定位到CPU占用过高的代码,分析其原因。
TIP:
(1)、通常可以结合jstat
来分析JVM中的内存信息;(如jstat -gcutil PID 1000 10
、jstat -gc PID 1000 10
、jstat -gccause PID 1000 10
)
(2)、jmap -heap PID
来查看整个JVM内存状态 ;(要注意的是在使用CMS GC
情况下,jmap -heap
的执行有可能会导致JAVA进程挂起)
(3)、jmap -histo PID
查看JVM堆中对象详细占用情况;
(4)、jmap -dump:format=b,file=文件名 [pid]
导出整个JVM中内存信息。
常见服务器CPU过高的问题原因和对应解决方案:
1、方法中存在读写文件流的操作,高并发时每个请求产生一个文件流,导致系统CPU急增。
解决方案:
从线程栈日志信息中,找出导致CPU高的线程方法。读写文件流操作移出方法中,避免每次请求都产生一个文件流。
2、方法中使用了多线程,未使用连接池或使用了Executors.newCachedThreadPool()创建的接连池,高并发时创建出过多的后台线程。
解决方案:
a、使用jstack命令统计出线程数量;
b、找出程序中创建线程代码;
c、使用Executors.newFixedThreadPool(thread_size)
创建固定数量的线程池(线程数固定,无法无收),或者使用new ThreadPoolExecutor(coreSize, maxSize, 60L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())
直接构造线程池。
3、发现是gc线程导致的CPU问题比较费时
解决方案:
a、查看一下gc策略是否合理;
b、用命令jmap -histo [PID]
分析是哪个类占用内存比较多,分析出可能存在内存泄露的地方;
c、jvm内存调优,可使用Jconsole、visalvm、probe
等工具查看java虚拟机中方法区、堆区(新生代、幸存代、老年代)、线程栈的内存分配,根据实际情况进行优化。
4、代码中存在死循环、死锁
解决方案:
直接通过jstack
获取到出问题的线程的堆栈信息,分析代码逻辑。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。