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

案例背景:

前段时间项目发布了一个V2.1.2大的版本以后,IDC机器CPU不时会突然飙升,而且是“根本停不下来”的样子,一上去了就是100%。想来也纳闷

虽然发了版本,但没有太耗CPU的功能,不应该会让CPU一下子从20%左右飙升到100%,而且是间歇性的,想想也应该是项目本身固有的bug,只不过现在访问量大了才暴露出来。

1、通过top命令看看是哪个进程当用了大量的CPU,得到pid

2、top -H -p [pid]找出此进程中CPU占用排在前头的活动线程,把pid都记录下来。

3、通过jstack -l [pid] >  [pid].stack,得到线程堆栈,看看各个线程都在做什么事情。根据上面记录下来的高CPU占用线程的pid在pid.stack文件中找到对应的线程,发现这几个线程都是GC线程。

这个时候我觉得应该是有内存泄露,导致GC过于频繁,于是jmap查看内存堆栈信息,并作了一些优化,还对原先的日志处理方式作了优化。

发布,看起来有效果,可正常运行了几天了后,又有两台机的CPU给飙上去了,看起来根本问题没有得到解决。

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

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

userAuthnBornTime是一个HashMap对象,更关键的是它是static的,也即所有对象公用,这个HashMap对象被用来保存登陆态的过期时间,很明显是读大于写,但是写也不少,在访问量大时,

大量的并发线程都需要操作这一个对象,导致很多读操作都处于忙等待状态。前面的在等待,后面还不停有请求进来,进一步加剧,因此在访问量突然增加时会直线飙升并且降不下来。

还是因此第一次太果断!

知道了原因,便得找解决方案了,了解Java的java.util.concurrent包自然会想到可以用ConcurrentHashMap来代替HashMap,以提高高并发情况下的性能,

ConcurrentHashMap不同于直接使用基于HashMap的同步操作的地方在于它内部同时保存了数据的多份拷贝,允许多个线程并发读,从而提高性能,

更多ConcurrentHashMap相关的介绍可找GOOGLE大神,相关文章太多了!

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

时间: 2024-07-31 18:46:54

一个Tomcat高CPU占用问题的定位的相关文章

一个线程相关的高CPU占用问题的定位

最近在重构项目代码时,发现两个线程同时访问一个加锁的std::list队列时,会出现恶性竞争锁的现象. 具体现象是A线程总是拿不到锁,B线程抢占几次后,A才抢占到. 由于是重构项目,也无法通过回滚代码来解决. 最终定位问题是,重构时对std::list队列单独封装了一个类导致的.单独封装一个类,那么每次push pop时都会多了一层函数堆栈. 删除该封装后,问题解决. 由此得出一个结论,对于频繁唤醒的读写线程,执行的操作应该尽量简单直接,避免冗余,避免进行过度的封装. 原文地址:https://

生产环境下JAVA进程高CPU占用故障排查

问题描述:生产环境下的某台tomcat7服务器,在刚发布时的时候一切都很正常,在运行一段时间后就出现CPU占用很高的问题,基本上是负载一天比一天高. 问题分析:1,程序属于CPU密集型,和开发沟通过,排除此类情况.2,程序代码有问题,出现死循环,可能性极大. 问题解决:1,开发那边无法排查代码某个模块有问题,从日志上也无法分析得出.2,记得原来通过strace跟踪的方法解决了一台PHP服务器CPU占用高的问题,但是通过这种方法无效,经过google搜索,发现可以通过下面的方法进行解决,那就尝试下

SQL 数据库高CPU占用语句排查

前述 最近一个项目CPU占用非常高,在IIS内设置CPU限制后系统频繁掉线,通过任务管理器发现SQLSever数据库占用CPU达到40%--70%,对于数据库本人也就处在增删查改几个操作水平层面,这次出了问题就硬着头皮上了,好在经过各种百度问题最终解决了,记性不好用的也不多,为防止忘掉就把主要排查方法记录下来. 查找耗时语句 SELECT TOP 10 total_worker_time/execution_count AS avg_cpu_cost, plan_handle, executio

Java线上应用故障排查之一:高CPU占用

一个应用占用CPU很高,除了确实是计算密集型应用之外,通常原因都是出现了死循环. (友情提示:本博文章欢迎转载,但请注明出处:hankchen,http://www.blogjava.net/hankchen) 以我们最近出现的一个实际故障为例,介绍怎么定位和解决这类问题. 根据top命令,发现PID为28555的Java进程占用CPU高达200%,出现故障. 通过ps aux | grep PID命令,可以进一步确定是tomcat进程出现了问题.但是,怎么定位到具体线程或者代码呢? 首先显示线

线上应用故障排查之一:高CPU占用

一个应用占用CPU很高,除了确实是计算密集型应用之外,通常原因都是出现了死循环. 以我们最近出现的一个实际故障为例,介绍怎么定位和解决这类问题. 根据top命令,发现PID为28555的Java进程占用CPU高达200%,出现故障. 通过ps aux | grep PID命令,可以进一步确定是tomcat进程出现了问题.但是,怎么定位到具体线程或者代码呢? 首先显示线程列表: ps -mp pid -o THREAD,tid,time 找到了耗时最高的线程28802,占用CPU时间快两个小时了!

压测过程中故障排查之一:高CPU占用问题分析案例

说明: 一个应用占用CPU很高,除了确实是计算密集型应用之外,通常原因都是出现了死循环 以我们最近出现的一个实际故障为例,介绍怎么定位和解决这类问题. 根据top命令,发现PID为28555的Java进程占用CPU高达200%,出现故障. 通过ps aux | grep PID命令,可以进一步确定是tomcat进程出现了问题.但是,怎么定位到具体线程或者代码呢? 首先显示线程列表: ps -mp pid -o THREAD,tid,time 找到了耗时最高的线程28802,占用CPU时间快两个小

线上应用故障排查之二:高内存占用

搞Java开发的,经常会碰到下面两种异常: 1.java.lang.OutOfMemoryError: PermGen space 2.java.lang.OutOfMemoryError: Java heap space 要详细解释这两种异常,需要简单重提下Java内存模型. Java内存模型是描述Java程序中各变量(实例域.静态域和数组元素)之间的关系,以及在实际计算机系统中将变量存储到内存和从内存取出变量这样的低层细节. 在Java虚拟机中,内存分为三个代:新生代(New).老生代(Ol

线上应用故障排查之二:高内存占用(转)

搞Java开发的,经常会碰到下面两种异常: 1.java.lang.OutOfMemoryError: PermGen space 2.java.lang.OutOfMemoryError: Java heap space 要详细解释这两种异常,需要简单重提下Java内存模型. (友情提示:本博文章转载,出处:hankchen,http://www.blogjava.net/hankchen) Java内存模型是描述Java程序中各变量(实例域.静态域和数组元素)之间的关系,以及在实际计算机系统

解决vs-code高cpu占用率问题

(microsoft.vscode.cpp.extension.darwin进程高cpu占用问题) 免费的vs-code现在已经成为mac/linux平台的码农新宠,毕竟从windows平台开发virsul studio多年的经验积累不是白给的. 我也从诸多的代码编辑器环境,逐渐迁移.统一到了vs-code.最近发现一启动vs-code,风扇就呼呼转,才开始还没注意,以为微软的Windows中二病做派再次发作了.后来逐渐感觉系统响应速度严重下降,仔细检查发现是一个进程CPU占用高企不坠:micr