系统load average相关参考这篇文章
Linux的负载高,主要是由于CPU使用、内存使用、IO消耗三部分构成。任意一项使用过多,都将导致服务器负载的急剧攀升。
这里说的是Java进程相关的几种场景排查
一、Java进程已死去
对于进程死去的,现场已经丢失,唯有查看留下的系统信息
1、系统活动情况 sar
# sar
11时00分01秒 CPU %user %nice %system %iowait %steal %idle
11时10分01秒 all 0.66 0.00 0.43 0.07 0.00 98.84
......
14时40分01秒 all 0.65 0.00 0.45 0.06 0.00 98.84
14时50分01秒 all 0.70 0.00 0.48 0.07 0.00 98.75
15时00分01秒 all 0.67 0.00 0.45 0.07 0.00 98.80
平均时间: all 0.62 0.00 0.45 0.06 0.00 98.87
# %user 用户空间的CPU使用
# %nice 改变过优先级的进程的CPU使用率
# %system 内核空间的CPU使用率
# %iowait CPU等待IO的百分比
# %steal 虚拟机使用的CPU
# %idle 空闲的CPU
# 在以上的显示当中,主要看%iowait和%idle,%iowait过高表示存在I/O瓶颈,即磁盘IO无法满足业务需求,
# 如果%idle过低表示CPU使用率比较严重,需要结合内存使用等情况判断CPU是否瓶颈。
2、查看是否OOM dmesg | egrep -i "oom|kill"
# dmesg | egrep "oom|kill"
[6710782.021013] java invoked oom-killer: gfp_mask=0xd0, order=0, oom_adj=0, oom_scoe_adj=0
[6710782.070639] [] ? oom_kill_process+0x68/0x140
[6710782.257588] Task in /LXC011175068174 killed as a result of limit of /LXC011175068174
[6710784.698347] Memory cgroup out of memory: Kill process 215701 (java) score 854 or sacrifice child
[6710784.707978] Killed process 215701, UID 679, (java) total-vm:11017300kB, anon-rss:7152432kB, file-rss:1232kB
3、分析JVM将死时打印的堆快照 (java_pid_PID.hprof)
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/www/logs
二、Java进程还在
1、查看当前GC情况 jstat -gcutil PID 1000 5
# jstat -gcutil 16098 1000 5
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
42.59 0.00 48.27 92.90 98.05 94.62 2342 7.320 7 0.615 7.935
42.59 0.00 48.27 92.90 98.05 94.62 2342 7.320 7 0.615 7.935
42.59 0.00 48.27 92.90 98.05 94.62 2342 7.320 7 0.615 7.935
42.59 0.00 48.27 92.90 98.05 94.62 2342 7.320 7 0.615 7.935
42.59 0.00 48.28 92.90 98.05 94.62 2342 7.320 7 0.615 7.935
2、查看Java进程里的线程情况 top -Hp PID
top - 15:39:23 up 78 days, 2:07, 1 user, load average: 0.00, 0.01, 0.05
Threads: 31 total, 0 running, 31 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.7 us, 0.3 sy, 0.0 ni, 99.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 1882764 total, 90700 free, 487076 used, 1304988 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 1196840 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
16114 root 20 0 2564060 225272 14160 S 0.3 12.0 2:10.02 java
16098 root 20 0 2564060 225272 14160 S 0.0 12.0 0:00.00 java
16099 root 20 0 2564060 225272 14160 S 0.0 12.0 0:04.18 java
16100 root 20 0 2564060 225272 14160 S 0.0 12.0 0:13.15 java
16101 root 20 0 2564060 225272 14160 S 0.0 12.0 0:00.03 java
3、打印Java进程的栈信息 jstack -l PID > jstack_PID_DATE.log
2018-08-25 19:19:48
Full thread dump OpenJDK 64-Bit Server VM (25.171-b10 mixed mode):
"Attach Listener" #43 daemon prio=9 os_prio=0 tid=0x00007fcb1818ee30 nid=0x4104 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
Locked ownable synchronizers:
- None
"Okio Watchdog" #33 daemon prio=5 os_prio=0 tid=0x00007fcb2c66ffd0 nid=0x3f02 in Object.wait() [0x00007fcb0e42a000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:460)
at okio.AsyncTimeout.awaitTimeout(AsyncTimeout.java:361)
at okio.AsyncTimeout$Watchdog.run(AsyncTimeout.java:312)
- locked <0x00000000edcc67c8> (a java.lang.Class for okio.AsyncTimeout)
Locked ownable synchronizers:
- None
上面的 nid=0x3f02 是 16130 的十六进制表示,根据 操作2和3 定位占用CPU高的线程堆栈
4、其他JDK小工具使用 (JDK内置帮助JVM故障定位与处理的几个小工具)
5、为此写的一键操作Shell脚本-SNAPSHOT
curl -s -O https://raw.githubusercontent.com/CherishCai/cjtools/master/cjtool.sh && sh cjtool.sh
6、另外的借鉴及工具
- 入门科普,围绕JVM的各种外挂技术
- 唯品会VJTools
- BTrace系: btrace、greys在线诊断工具
7、可能涉及的操作命令
#查看Java进程
jps -l | grep -vi jps
ls /tmp/hsperfdata_*
ps axu | grep -v 'grep' | egrep 'java|PID'
#查看进程PID的线程情况 (-i排除idle线程)
top -Hp PID
#打印堆栈信息到文件
jstack -l PID > jstack_PID_xxx.txt
#虚拟机统计信息;查看当前jvm使用情况
jstat -gcutil PID 1000 10
#System Activity Reporter系统活动情况报告
sar
#Linux命令dmesg用来显示开机信息,可用于查看是否有Java进程OOM
dmesg | egrep -i "oom|kill"
#十进制转十六进制(\n换行)
printf '%x\n' N