性能分析--JVM--Arthas入门
1 概述
针对性能问题,判断和分析起来是极其复杂的,那么有什么简单易用的方法来确定问题原因呢?在此,我们介绍一个武器-Arthas,通过这个工具的几个命令的使用来讲解如何分析性能问题。
Arthas是Alibaba开源的Java诊断工具,可以用于在线排查问题,动态跟踪Java代码,实时监控JVM状态,这些特性正是分析苍穹性能问题需要的。
首先,实际生产环境中,容器众多,要确定具体哪个容器有问题,还是有点难度的,我们建议通过金蝶云GPaaS平台的容器监控或者kubectl命令来请确定高负载的容器,然后再进入对应容器使用Arthas进行详细跟踪。
2 安装工具
在官方文档中,一般使用java -jar arthas-boot.jar这个jar来下载完整程序包后启动Arthas的,但是由于客户网络环境差异很大,不是所有的环境都能访问公网的,因此,我们提供一个离线的版本v3.4.4,可以直接放到容器中,解压后启动。
下载地址(复制链接和提取码到百度云):
链接:Arthas
提取码:7dzu
这个压缩包的shell,小编做了修改,取消了一些命令工具的检查,苍穹标准容器可以正常运行。但是,telnet工具Arthas强依赖的,是容器中必须存在的。
2.1 上传tar包
如果使用金蝶云GPaaS平台,请参考下面的方法。如果使用其他容器平台,使用#docker cp命令将tar文件拷贝到容器内;如果使用非容器部署,则忽略这一步骤。
2.2 解压tar包
使用命令#tar xvf arthas.tar.gz进行解压。
2.3 启用Arthas
进入解压后的目录,使用#./as.sh 1附加到苍穹进程。
3 CPU瓶颈
常见的性能问题,大多都可以通过首先检查CPU得以确诊或者确认,GC线程或者VM Thread高负载提示内存回收问题,说明内存使用存在瓶颈;业务线程高负载提示业务逻辑存在缺陷。那么第一斧子就是监控CPU使用率。
如果苍穹进程不能挂载Arthas,或者处于CPU严重超载时,我们建议通过如下shell来获取最耗时的线程:
# top -b -d2 -n3 -H -p 1 | grep 'top -' -A 17 > slow.log && /jdk/bin/jstack -l 1 >> slow.log
间隔2秒,获取3次进程1的前10个最耗费CPU的线程信息,并与线程堆栈一起输出到文件slow.log中,然后通过线程号找到最耗费CPU的线程。
但是,大多数场合中,Arthas还是能够后正确地附加到苍穹进程的,在Arthas启动后,使用命令$thread –n 2 –I 5000就可以监控在5秒内,最耗费CPU的两个线程并打印堆栈。
上图中,cpuUsage就是5秒内最消耗CPU的线程及其堆栈,通过这个方法就可以轻松方便地定位出有问题的线程。如果CPU使用率高的线程是Service Thread、Finalizer、VM Thread、JIT编译、GC等系统线程,则需要从系统本身或者内存等方面继续跟踪;如果线程是
DubboServerHandler、http-request-pool、scheduleTask-BIZJOB以及RabbitMqAsyncConsumer这一类业务线程,需要重点关注对应业务代码的类和方法。
4 监控方法
如果说第一斧子是找到了最耗时的线程堆栈中的类和方法,那么第二斧就是跟踪业务代码的执行频率和耗时了。
当我们确定对应的疑似有性能问题的方法时,我们可以继续跟踪器执行频率和响应时间,使用命令$ monitor 类 方法 -c 5来间隔5秒监控方法的执行,如果执行频率太高或者响应时间太长都是提示性能问题。例如下图这个监控SQL执行频率的示例。
上图中,重点关注avg-rt和调用次数,高频和执行时间长都是在提示性能问题。
5 火焰图
当前两斧子都找不到问题时,最后还有一个大招就是火焰图了,通过火焰图,可以精确地描述进程在某个时间段内的所有CPU调用,并构造出方法调用的火焰图,通过各个方法的长短比例就可以定位出性能瓶颈是什么了。
当然单纯使用火焰图,是无法精确找到某个耗时方法的,还需要和具体的业务动作相结合,才能更快地定位瓶颈,例如审核动作慢,那么一定是在慢在audit方法;数据加载慢,那么很可能慢在loaddata一类的方法中。此时与苍穹Monitor的线程堆栈配合使用是个很好的思路。
我们建议获取火焰图时,使用线程进行隔离,命令$profiler start --include'java/lang/*' --threads开始启动火焰图抓取,在对应跟踪周期结束时,使用命令$profiler stop 来结束跟踪并构建火焰图。
当使用火焰图时,需要注意以下几点:
y 轴表示调用栈,每一层都是一个函数。调用栈越深,火焰就越高,顶部就是正在执行的函数,下方都是它的父函数;
x 轴表示抽样数,如果一个函数在 x 轴占据的宽度越宽,就表示它被抽到的次数多,即执行的时间长。注意,x 轴不代表时间,而是所有的调用栈合并后,按字母顺序排列的;
火焰图就是看顶层的哪个函数占据的宽度最大。只要有"平顶"(plateaus),就表示该函数可能存在性能问题;
右侧的系统线程java_start宽度过大往往是提示GC、JIT等JVM的性能问题,在关注点为业务线程时,可以忽略这些线程;
按照每个线程的方法调用逐层展开,哪一个业务代码占用宽度最长,那么CPU瓶颈基本就在这里了。
最后留一下思考题,下图中方法kd.bos.ksql.shell.KDResultSet.next的性能瓶颈在哪里呢?
参考资料
http://arthas.gitee.io/
http://www.ruanyifeng.com/blog/2017/09/flame-graph.html
https://github.com/jvm-profiling-tools/async-profiler
性能分析--JVM--Arthas入门
本文2024-09-23 01:12:19发表“云苍穹知识”栏目。
本文链接:https://wenku.my7c.com/article/kingdee-cangqiong-144445.html