一个Tomcat高CPU占用问题的定位

      前段时间项目(交接过来的)发布了一个大的版本以后,IDC机器CPU不时会突然飙升,而且是“根本停不下来”的样子,一上去了就是100%。想来也纳闷,虽然发了版本,但没有太耗CPU的功能,不应该会让CPU一下子从20%左右飙升到100%,而且是间歇性的,想想也应该是项目本身固有的bug,只不过现在访问量大了才暴露出来。

先top命令看看是哪个进程当用了大量的CPU,得到pid,继续top -H -p [pid]找出此进程中CPU占用排在前头的活动线程,把pid都记录下来。

接下来jstack -l [pid] >  [pid].stack,得到线程堆栈,看看各个线程都在做什么事情。根据上面记录下来的高CPU占用线程的pid在pid.stack文件中找到对应的线程,发现这几个线程都是GC线程。这个时候我觉得应该是有内存泄露,导致GC过于频繁,于是jmap查看内存堆栈信息,并作了一些优化,还对原先的日志处理方式作了优化。发布,看起来有效果,可正常运行了几天了后,又有两台机的CPU给飙上去了,看起来根本问题没有得到解决。

我还是太年轻,太粗心。

又得重新来分析了! 先vmstat来看看机器的情况,发现当前的排队线程有时高达76,低时也有10个以上,已经超出了CPU数。

既然是线程问题,还是jstack -l [pid] 来看线程堆栈,这次不再草草下结论,细细看每个线程都在干啥!发现有很多线程的执行都停留在saveUserAuthDetails方法中某一行:

userAuthnBornTime是一个HashMap对象,更关键的是它是static的,也即所有对象公用,这个HashMap对象被用来保存登陆态的过期时间,很明显是读大于写,但是写也不少,在访问量大时,大量的并发线程都需要操作这一个对象,导致很多读操作都处于忙等待状态。前面的在等待,后面还不停有请求进来,进一步加剧,因此在访问量突然增加时会直线飙升并且降不下来。

还是因此第一次太果断!

知道了原因,便得找解决方案了,了解Javajava.util.concurrent包自然会想到可以用ConcurrentHashMap来代替HashMap,以提高高并发情况下的性能,ConcurrentHashMap不同于直接使用基于HashMap的同步操作的地方在于它内部同时保存了数据的多份拷贝,允许多个线程并发读,从而提高性能,更多ConcurrentHashMap相关的介绍可找GOOGLE大神,相关文章太多了!

使用ConcurrentHashMap替换HashMap以后,果然机器CPU都能稳定在20%左右。

友情提示:ConcurrentHashMap对于key和value都不允许为空(记得做判断,不然出大事)

转载自jmatrix

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值