在测试环境测试时,发现某服务响应有点慢,于是ssh到对应环境,查看CPU使用率:使用后top命令,我看到结果是这样的。我们知道,tomcatcpu负载高通常是:1.代码问题:死循环,并发线程数多,计算量大2.full-gc:产生大对象,对象引用无法释放,所以我尝试用jstack来分析问题,先用jstack-l119236|grep'java.lang.Thread.State'|wc-l统计线程数,可以看到总共有679个线程,然后分别统计RUNNABLE线程数jstack-l119236|grep'java.lang.Thread.State:RUNNABLE'|wc-lWAITING线程数jstack-l119236|grep'java.lang.Thread.State:WAITING'|wc-lTIMED_WAITING线程数jstack-l119236|grep'java.lang.Thread.State:TIMED_WAITING'|wc-lBLOCKED线程计数jstack-l119236|grep'java.lang.Thread.State:BLOCKED'|wc-l和死锁线程计数jstack-l119236|grep'Java级死锁'|wc-l可以看到经过一次操作,我们知道这个进程当前有679个线程,其中79个线程处于RUNNABLE(线程运行或I/O等待状态)347个线程处于WAITING状态(无限期等待forwake-up)66个threadsareinTIMED_WAITING(waitingforwake-up,butthetimelimitisset)0个threadsintheBLOCKEDstate(waitingforamonitorlockstate)Nodeadlockisfoundsince如果没有死锁,让我们看看哪些线程导致了高占用率?接下来我们使用命令查看线程top-Hp119236在进程119236中占用最高的线程,我们发现这是122318占用率很高,达到了45%,所以我们进一步将线程的pid转为16进制输出printf"%x\n"122318然后使用jstack119236|grep1ddce-A30查看线程的具体信息with入住率最高。redission的线程作为分布式缓存锁,该线程CPU占用率高是正常的。然后我们使用jstat-gcutil119236查看java进程的gc状态,可以看到连续多次查询YGC(MinorGC)的次数如果参数设置合理,系统没有超时日志,GC频率不高,GC耗时不高,则无需进行GC优化;如果GC时间超过1~3秒,或者GC频繁,必须优化如果满足以下指标,一般不需要GC:■MinorGC执行时间小于50ms;■MinorGC执行时间不频繁,大约10秒一次;■FullGC执行时间小于1s;但是因为我们的YGC次数太多,考虑到年轻代的配置可能太小了,根据pid找到对应的tomcat应用psaux|greppid(我这里重启了实例,所以上下文中的pid有变化)查看启动脚本中JVM的相应配置后发现Xmn的大小为170m。官方推荐的Xmn大小是整个堆内存的3/8左右。同时,我们将最大堆内存调整为768m来尝试修复这个问题。重启实例后,再次使用jstat查看gc情况,发现ygc明显下降。
