前言:
最近几次,公司的java服务项目,占用CPU很高,持续不下降,云里雾里,一直不知道是什么原因造成了cpu占用高。此片文章谈谈从发现这个问题到解决这个问题的过程。
我们试着利用lstack打出dump信息,观察是哪个线程占用cpu高。
1.先用top查询某进程的线程CPU占用情况,定位到cpu占用高的进程pid
根据pid定位具体的线程top -p PID -H
2.用jstack -l PID >> 28137.log 将具体的线程导入到文件中
3.在文件中搜索线程id(需要转成16进制小写)
如 上图中的28249 的 16进制为 6e59
在 28137.log 文件中查找 6e59 即可定位到具体的具体的堆栈代码
查找发现 代码定位于使用的是google guava 下的LinkedHashMultimap导致cpu居高不下
为什么此map导致cpu占用如此高了 就问问了最近运维的情况, 最近运营那边加大了推量,峰值的时候qps 达到了5000 晚上在线的用户达到了10W级别的用户量,而此map存放了用户相关属性的数据,但是在上线的时候 我们专门测试了ConcurrentHashMap 和 LinkedHashMultimap的性能,操作100W数据的时候 基本都是维持在2-3秒内,速度都差不多,是很快的速度,最后也就选择了LinkedHashMultimap,毕竟用起来方便 在存放一对多的情况下。
但是为什么LinkedHashMultimap 占用cpu高了 试着看了源码,发现LinkedHashMultimap内部的实现很复杂,特别是在做增删改的频繁的情况下,用到了计数器,在存放量大的情况下,删除和增加是个很耗时的工作,那几天我们存放的数据基本都是维持在10W 以上的数据。
找到了问题根源,我们就将LinkedHashMultimap换成了ConcurrentHashMap,升级到生产环境,发现cpu降下来了 ,此问题也就解决了。当一次记录,避免此问题以后再次发生。
最后附上我的ConcurrentHashMap和LinkedHashMultimap并发性能测试
系统环境 windows 64位 8G 内存 双核 (如果不准,请自行测试验证)
后记:如果发现什么问题 ,请留言给我,我是小志码子,我会及时改正,互相学习,共同进步。