线上问题排查指南

排查CPU使用率过高

1.先通过top命令找到消耗CPU很高的进程ID,假设是我们找到的进程ID是10923

top

2.执行top -p 10923 -H,获取当前进程下所有线程的信息

topH

3.找到其中消耗CPU特别高的线程ID,如10924

4.将第三步获取到的线程ID转成十六进制10924 -> 0x2aac

5.执行jstack 10923 > jstack10923.out对当前进程做dump操作,并输出所有的线程信息

6.找到对应的线程信息内容cat jstack10923.out | grep 2aac -C 10
thread

排查OOM的问题

1.先通过top命令找到消耗内存很高的进程ID,假设是我们找到的进程ID是10923

top1

2.使用jstat -gcutil 10923 1000 10工具按照指定间隔,看一下统计信息,这里会每隔一段时间显示一下,包括新生代的两个S0、s1区、Eden区,以及老年代的内存使用率,还有young gc以及full gc的次数。其中1000代表的是1000毫秒,10代表的打印10次

1
2
3
4
5
6
7
8
9
10
11
12
[root@zyj tmp]# jstat -gcutil 10923 1000 10
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 39.80 9.11 72.72 97.87 95.09 327 1.111 3 0.191 1.302
0.00 39.80 9.11 72.72 97.87 95.09 327 1.111 3 0.191 1.302
0.00 39.80 9.11 72.72 97.87 95.09 327 1.111 3 0.191 1.302
0.00 39.80 9.11 72.72 97.87 95.09 327 1.111 3 0.191 1.302
0.00 39.80 9.13 72.72 97.87 95.09 327 1.111 3 0.191 1.302
0.00 39.80 9.13 72.72 97.87 95.09 327 1.111 3 0.191 1.302
0.00 39.80 9.13 72.72 97.87 95.09 327 1.111 3 0.191 1.302
0.00 39.80 9.13 72.72 97.87 95.09 327 1.111 3 0.191 1.302
0.00 39.80 9.13 72.72 97.87 95.09 327 1.111 3 0.191 1.302
0.00 39.80 9.15 72.72 97.87 95.09 327 1.111 3 0.191 1.302
1
2
3
4
5
6
7
8
9
10
S0     Heap上的Survivor space 0区已使用空间的百分比
S1 Heap上的Survivor space 1区已使用空间的百分比
E Heap上的Eden space区已使用空间的百分比
O Heap上的Old space区已使用空间的百分比
P Perm space区已使用的空间百分比
YGC 从应用程序启动到采样时发生的Young GC的次数
YGCT 从应用程序启动到采样时发生的Young GC所用的时间(单位秒)
FGC 从应用程序启动到采样时发生的Full GC的次数
FGCT 从应用程序启动到采样时Full GC所用的时间(单位秒)
GCT 从应用程序启动到采样时用于垃圾回收的总时间(单位秒)
1
2
S0      S1       E       O      YGC     FGC
26.80 0.00 10.50 89.90 86 954

其实如果大家了解原理,应该知道,一般来说大量的对象涌入内存,结果始终不能回收,会出现的情况就是,快速撑满年轻代,然后young gc几次,根本回收不了什么对象,导致survivor区根本放不下,然后大量对象涌入老年代。老年代很快也满了,然后就频繁full gc,但是也回收不掉。

然后对象持续增加不就oom了,内存放不下了,爆了呗。

所以jstat先看一下基本情况,马上就能看出来,其实就是大量对象没法回收,一直在内存里占据着,然后就差不多内存快爆了。

3.使用jmap -histo 10923命令查看可以打印出当前堆中所有每个类的实例数量和内存占用,如下,class name是每个类的类名[B是byte类型,[C是char类型,[I是int类型,bytes是这个类的所有示例占用内存大小,instances是这个类的实例数量。

4.使用jmap -dump:format=b,file=/tmp/10923dump.hprof 10923接着就可以使用Jprofiler工具看下是哪个对象占用空间最大了。

dump信息

人家肯定会问你有没有处理过线上的问题,你就说有,最简单的,你说有个小伙子用了本地缓存,就放map里,结果没控制map大小,可以无限扩容,最终导致内存爆了,后来解决方案就是用了一个GuavaCache框架,通过过期策略清理掉旧数据,控制内存占用就好了。

另外,务必提到,线上jvm必须配置-XX:+HeapDumpOnOutOfMemoryError,-XX:HeapDumpPath=/path/heap/dump。因为这样就是说OOM的时候自动导出一份内存快照,你就可以分析发生OOM时的内存快照了,到底是哪里出现的问题。