1. 定位cup占用过高步骤
    1
    2
    3
    4
    5
    6
    1.top定位进程PID。如7888
    2.找到PID,java -aux|grep PID,定位该进程所在的应用路径。如java -aux|grep 7888
    3.top -H -p PID,找到该进程中的线程ID(默认按照CPU占用率降序)。如top -H -p 7888找到8072
    4.使用printf %x PID,对找到的PID转成十六进制。如8072转为1f88
    5.cd到2中找到的jdk路径下,执行./jstack PID|grep -A 5 十六进制(id)。
    如./jstack 7888|grep -A 5 1f88,找到1f88线程后5行的内容
  2. 具体例子
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    Java Web应用Load飙高排查思路
    1、使用uptime查看当前load,发现load飙高。
    ~ uptime
    13:29 up 23:41, 3 users, load averages: 10 10 10

    2、使用top命令,查看占用CPU较高的进程ID。
    ~ top
    PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
    1893 admin 20 0 7127m 2.6g 38m S 181.7 32.6 10:20.26 java

    发现PID为1893的进程占用CPU 181%。而且是一个Java进程,基本断定是软件问题。
    3、使用 top命令,查看具体是哪个线程占用率较高
    ~ top -Hp 1893
    PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
    4519 admin 20 0 7127m 2.6g 38m R 18.6 32.6 0:40.11 java

    4、使用printf命令查看这个线程的16进制
    ~ printf %x 4519
    11a7
    复制代码
    5、使用jstack命令查看当前线程正在执行的方法。
    ~ jstack 1893 |grep -A 200 11a7
    "thread-5" #500 daemon prio=10 os_prio=0 tid=0x00007f632314a800 nid=0x11a2 runnable [0x000000005442a000]
    java.lang.Thread.State: RUNNABLE
    at sun.misc.URLClassPath$Loader.findResource(URLClassPath.java:684)
    at sun.misc.URLClassPath.findResource(URLClassPath.java:188)
    at java.net.URLClassLoader$2.run(URLClassLoader.java:569)
    at java.net.URLClassLoader$2.run(URLClassLoader.java:567)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findResource(URLClassLoader.java:566)
    at org.hibernate.validator.internal.xml.ValidationXmlParser.getInputStreamForPath(ValidationXmlParser.java:248)
    at com.hollis.test.util.BeanValidator.validate(BeanValidator.java:30)
    1
    2
    3
    4
    5
    从上面的线程的栈日志中,可以发现,当前占用CPU较高的线程正在执行我代码的com.hollis.test.util.BeanValidator.validate(BeanValidator.java:30)类。那么就可以去排查这个类是否用法有问题了。
    分析Linux Load高时的一个误区
    区分了R和D状态线程对Linux load的影响,我们再来看一个绝大多数人都曾经历的误区。当linux系统load标高时,很多人都会去top一下,查看当前系统谁占用的CPU Usage最高。
    这里补充一个背景知识,只有当进程(线程)处于R状态时,才耗费CPU Usage,其他状态(包括D状态)并不耗费CPU Usage。当load高主要是由D状态线程数量过多导致的时候,此时从top中按CPU Usage的排名是不会发现任何线索的。
    即使当load高是由R状态线程数量过多导致,如果运行top命令时导致load高的R状态线程已经结束,此时也不会从按CPU Usage的排名的top输出中发现线索的。默认情况下,top命令是3秒中刷新,只显示3秒内的CPU Usage信息。