前因
收到线上服务器CPU使用率100%的告警信息。
环境
- jdk1.8
- CentOS Linux ;CentOS Linux
排查
查看服务器CPU使用率
果然cpu已经达到了100%了
命令 top
使用arthas工具 使用方式 arthas
-
执行命令
java -jar arthas-boot.jar
-
然后执行命令
thread
看到有两个线程cpu非常高,很奇怪竟然有一个是 GC线程,后面再说
-
再执行命令
thread -n 3
列出前三个最忙的线程
找打了这个线程栈了,发现是查询数据库导致的,DAO的方式是getUserInfoByMobile
-
拿到方法入参,查询发现需要从数据库中,load出一千多万行数据。
真相
真相就在这,由于表中存在大量没有手机号的数据,这时入参没有做非空校验,导致直接查询出全部没有手机号的数据,并load出这些数据。
原始sql
select * from user where mobile = "";
解决方案
这就好解决了,业务场景是判断当前手机号是否已经存在,在此处做修改,如果当前手机号是空的我就不需要在查询数据库,所以我只需要做手机号字符串非空校验即可。
小结
至于为什么GC线程的CPU也是很高呢,也正是因为需要从数据库中load出一千多万条数据到虚拟机栈中,但是由于JVM中的年轻代空间大小有限,所以需要进行垃圾回收,而垃圾回收本身就对CPU使用率较高,而且又GC连续频繁执行。