记一次JavaWeb程序的CPU占用过高的分析过程

最近负责的一个项目,项目启动一段时间之后CPU占用率一直在90%以上浮动,检查之后没有死循环,十分不解,于是一直在检测,然后找到了问题代码,记录一下找这个问题的过程。


服务器配置是阿里云的服务器 E5-2630的单核,内存2GB。操作系统是Windows Server 2008  (x64),Java虚拟机是Tomcat v7.0.

首先是mysql.exe 的cpu占用率过高,首先用show processlist命令找出最频繁的sql语句,然后关键问题在于此数据库中除了主键之外没有其他索引,猜测是因为数据的参数设置问题。于是做了如下调整

1、把MySQL的tmp_table_size加大到200M

2、给用到频率最高的语句的where筛选字段添加索引


增加完毕之后MySQL进程的cpu占用明显下降,而且内存稳定在300MB左右,没有明显增加。数据库调整完成。



然后是java.exe进程占用CPU很高,而且没有死循环,于是下载了微软的process explorer工具对java.exe进行进行监控,找到了其pid号为xxxx,然后查看详情之后发现,其中的两个线程占用的cpu特别高,然后记下这两个线程的tid号。下面想办法找到这两个线程的运行日志。

 

首先,尝试采用jdk自带的jstack抓取日志,但是报错了,像这样

C:\Users\Administrator>jstack -l 8736
8736: Insufficient memory or insufficient privileges to attach
The -F option can be used when the target process is not responding

报  Insufficient memory or insufficient privileges to attach
The -F option can be used when the target process is not responding

其实,加上-F参数并没有卵用,根本原因是,权限问题。出现这个错误的原因是我的tomcat进程是调用了系统的start service自动启动的,而我的jstack是自己在命令行上面启动的,虽然看上去都是一个administrator用户下的,但是其实tomcat进程并不是。

于是我把tomcat服务停掉,然后手动点击tomcat的bin目录下的startup.bat启动了tomcat,此时再调用

jstack -l 3254 >c:\stack.log

命令,将java.exe的进程日志输出到文件,你会发现jstack命令好用了。


然后用notpad++之类的工具打开log文件,将上面记录的pid转化为16进制,用转化后的线程号在log文件中进行搜索,我运气比较好,直接定位到了具体的方法。发现这是个通用的方法,是按照属性在数据库中查询对应的实体类的方法。


方法名字是findByProperties(xxxx, start, limit);


一开始没发现该方法的异常,后来发现,同事不小心把start赋值为了0,这样用户每点击一下下一页,其实加载的是从0开始到目的页面的值,这样下去越加载越多。最终导致cpu负载爆表。


将start改为真实变量之后问题解决。



你可能感兴趣的:(J2EE,数据库)