这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 综合技术 » 工业控制与自动化 » Java线上故障排查必备指南(完整版)(1)

共1条 1/1 1 跳转至

Java线上故障排查必备指南(完整版)(1)

专家
2020-05-14 08:07:19     打赏

线上故障主要会包括 CPU、磁盘、内存以及网络问题,而大多数故障可能会包含不止一个层面的问题,所以进行排查时候尽量四个方面依次排查一遍。同时例如 jstack、jmap 等工具也是不囿于一个方面的问题的,基本上出问题就是 df、free、top 三连,然后依次 jstack、jmap 伺候,具体问题具体分析即可。

CPU
一般来讲我们首先会排查 CPU 方面的问题。CPU 异常往往还是比较好定位的。原因包括业务逻辑问题(死循环)、频繁 gc 以及上下文切换过多。而最常见的往往是业务逻辑(或者框架逻辑)导致的,可以使用 jstack 来分析对应的堆栈情况。使用 jstack 分析 CPU 问题我们先用 ps 命令找到对应进程的 pid(如果你有好几个目标进程,可以先用 top 看一下哪个占用比较高)。

接着用top -H -p pid来找到 CPU 使用率比较高的一些线程

图片16.png 

然后将占用最高的 pid 转换为 16 进制printf '%x\n' pid得到 nid

图片15.png 

接着直接在 jstack 中找到相应的堆栈信息jstack pid |grep 'nid' -C5 –color图片14.png

 

可以看到我们已经找到了 nid 为 0x42 的堆栈信息,接着只要仔细分析一番即可。当然更常见的是我们对整个 jstack 文件进行分析,通常我们会比较关注 WAITING 和 TIMED_WAITING 的部分,BLOCKED 就不用说了。我们可以使用命令cat jstack.log | grep "java.lang.Thread.State" | sort -nr | uniq -c来对 jstack 的状态有一个整体的把握,如果 WAITING 之类的特别多,那么多半是有问题啦。图片13.png

频繁 gc当然我们还是会使用 jstack 来分析问题,但有时候我们可以先确定下 gc 是不是太频繁,使用jstat -gc pid 1000命令来对 gc 分代变化情况进行观察,1000 表示采样间隔(ms),S0C/S1C、S0U/S1U、EC/EU、OC/OU、MC/MU 分别代表两个 Survivor 区、Eden 区、老年代、元数据区的容量和使用量。YGC/YGT、FGC/FGCT、GCT 则代表 YoungGc、FullGc 的耗时和次数以及总耗时。如果看到 gc 比较频繁,再针对 gc 方面做进一步分析,具体可以参考一下 gc 章节的描述。

图片12.png 

上下文切换针对频繁上下文问题,我们可以使用vmstat命令来进行查看

图片11.png 

cs(context switch)一列则代表了上下文切换的次数。

如果我们希望对特定的 pid 进行监控那么可以使用 pidstat -w pid命令,cswch 和 nvcswch 表示自愿及非自愿切换。

 

图片10.png 

磁盘

磁盘问题和 CPU 一样是属于比较基础的。首先是磁盘空间方面,我们直接使用df  -hl来查看文件系统状态

图片9.png 

更多时候,磁盘问题还是性能上的问题。我们可以通过 iostatiostat -d -k -x来进行分析

图片8.png 

最后一列%util可以看到每块磁盘写入的程度,而rrqpm/s以及wrqm/s分别表示读写速度,一般就能帮助定位到具体哪块磁盘出现问题了。

另外我们还需要知道是哪个进程在进行读写,一般来说开发自己心里有数,或者用 iotop 命令来进行定位文件读写的来源。

图片7.png 

不过这边拿到的是 tid,我们要转换成 pid,可以通过 readlink 来找到 pidreadlink -f /proc/*/task/tid/../..。

 

找到 pid 之后就可以看这个进程具体的读写情况cat /proc/pid/io

图片6.png 

我们还可以通过 lsof 命令来确定具体的文件读写情况lsof -p pid

图片5.png 

内存

内存问题排查起来相对比 CPU 麻烦一些,场景也比较多。主要包括 OOM、GC 问题和堆外内存。一般来讲,我们会先用free命令先来检查一发内存的各种情况。

图片4.png 

堆内内存

内存问题大多还都是堆内内存问题。表象上主要分为 OOM 和 Stack Overflo。

OOM

JMV 中的内存不足,OOM 大致可以分为以下几种:

Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native thread

这个意思是没有足够的内存空间给线程分配 Java 栈,基本上还是线程池代码写的有问题,比如说忘记 shutdown,所以说应该首先从代码层面来寻找问题,使用 jstack 或者 jmap。如果一切都正常,JVM 方面可以通过指定Xss来减少单个 thread stack 的大小。另外也可以在系统层面,可以通过修改/etc/security/limits.confnofile 和 nproc 来增大 os 对线程的限制

图片3.png 

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space这个意思是堆的内存占用已经达到-Xmx 设置的最大值,应该是最常见的 OOM 错误了。解决思路仍然是先应该在代码中找,怀疑存在内存泄漏,通过 jstack 和 jmap 去定位问题。如果说一切都正常,才需要通过调整Xmx的值来扩大内存。Caused by: java.lang.OutOfMemoryError: Meta space这个意思是元数据区的内存占用已经达到XX:MaxMetaspaceSize设置的最大值,排查思路和上面的一致,参数方面可以通过XX:MaxPermSize来进行调整(这里就不说 1.8 以前的永久代了)。Stack Overflow栈内存溢出,这个大家见到也比较多。Exception in thread "main" java.lang.StackOverflowError表示线程栈需要的内存大于 Xss 值,同样也是先进行排查,参数方面通过Xss来调整,但调整的太大可能又会引起 OOM。使用 JMAP 定位代码内存泄漏上述关于 OOM 和 Stack Overflo 的代码排查方面,我们一般使用 JMAPjmap -dump:format=b,file=filename pid来导出 dump 文件

图片2.png 

通过 mat(Eclipse Memory Analysis Tools)导入 dump 文件进行分析,内存泄漏问题一般我们直接选 Leak Suspects 即可,mat 给出了内存泄漏的建议。另外也可以选择 Top Consumers 来查看最大对象报告。和线程相关的问题可以选择 thread overview 进行分析。除此之外就是选择 Histogram 类概览来自己慢慢分析,大家可以搜搜 mat 的相关教程。

图片1.png 

日常开发中,代码产生内存泄漏是比较常见的事,并且比较隐蔽,需要开发者更加关注细节。比如说每次请求都 new 对象,导致大量重复创建对象;进行文件流操作但未正确关闭;手动不当触发 gc;ByteBuffer 缓存分配不合理等都会造成代码 OOM。

另一方面,我们可以在启动参数中指定-XX:+HeapDumpOnOutOfMemoryError来保存 OOM 时的 dump 文件。





关键词: 线上     故障     排查     必备     指南    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]