在测试环境进行测试时,发现某个服务响应有一点点慢,于是ssh到对应环境,查看了一下cpu占用情况:
在使用top
指令之后 看到的结果是这样的
文章图片
正如我们所知道的tomcat cpu 负载高 通常是:
1、代码问题:死循环、大量并发线程计算量大
2、full-gc : 有大对象产生、 对象引用无法释放
于是试图使用jstack命令分析问题
首先使用
jstack -l 119236 | grep 'java.lang.Thread.State' | wc -l
统计了一下线程数
文章图片
可以看到一共有679个线程
然后又分别统计了
RUNNABLE线程数
jstack -l 119236 | grep 'java.lang.Thread.State: RUNNABLE' | wc -l
WAITING的线程数
jstack -l 119236 | grep 'java.lang.Thread.State: WAITING' | wc -l
TIMED_WAITING的线程数
jstack -l 119236 | grep 'java.lang.Thread.State: TIMED_WAITING'| wc -l
BLOCKED的线程数
jstack -l 119236 | grep 'java.lang.Thread.State:BLOCKED'| wc -l
以及死锁(deadlock)的线程数
jstack -l 119236 | grep 'Java-level deadlock'| wc -l
文章图片
可以看到,一顿操作下来
我们知道了目前这个进程中 一共有 679个线程 其中有
79个线程处于RUNNABLE (线程运行中或I/O等待状态)
347个线程处于线程在WAITING (无限等待唤醒的状态)
66个线程在TIMED_WAITING (等待唤醒,但设置了时限的状态)
0个线程处于BLOCKED状态 (等待一个monitor lock的状态)
没有发现死锁
既然没有死锁 那我们看看导致是哪些线程导致了占用高呢?
接下来我们使用指令 查看进程119236中 占用最高的线程
top -Hp 119236
文章图片
我们发现 这个122318占用非常高 达到了45%,于是我们进一步将该线程的pid转为16进制输出
printf "%x\n" 122318
文章图片
随后使用
jstack 119236 |grep 1ddce -A 30
看到占用最高的线程的具体信息
文章图片
发现只是redission的线程,作为一个分布式缓存锁,该线程cpu占用高属于正常情况
随后我们使用
jstat -gcutil 119236
查看该java进程的gc情况
文章图片
可以看到在多次连续的查询中YGC(Minor GC)的次数非常多,但是实际消耗的时间还是比较合理的。
如果各项参数设置合理,系统没有超时日志出现,GC频率不高,GC耗时不高,那么没有必要进行GC优化;如果GC时间超过1?3 秒,或者频繁G C ,则必须优化。如果满足下面的指标,则一般不需要进行GC:
■ Minor GC执行时间不到50ms;
■ Minor GC执行不频繁,约10秒一次;
■ Full GC执行时间不到1s;
【记录一次使用jstack和jstat分析线程问题实践】所以本次实际从线程分析和gc分析的角度来看,服务并无异常,或许我该去看看接口,溜了溜了