热点新闻
阿里开源Java诊断工具 Arthas 使用
2023-07-09 10:03  浏览:311  搜索引擎搜索“错改B2B”
温馨提示:为防找不到此信息,请务必收藏信息以备急用! 联系我时,请说明是在错改B2B看到的信息,谢谢。
展会发布 展会网站大全 报名观展合作 软文发布

Arthas 是阿里开源的 Java 诊断工具,相比 JDK 内置的诊断工具,要更人性化,并且功能强大,可以实现许多问题的一键定位,是我用到的最方便的诊断工具。
下载和安装见官网 https://arthas.aliyun.com/doc/profiler.html
下面记录一些我工作中常用到的指令

1. dashboard : 展示当前进程信息

主要是两部分: 线程信息(按照cpu使用率倒序) 和 内存信息
可以快速发现 当前前几个cpu使用高的线程




image.png

2. thread :查看当前 JVM 的线程堆栈信息




image.png

thread : 获取当前所有线程 (按照cpu使用率倒序) thread 4602 threathe : 获取指定线程堆栈信息 thread -n 8 : 当前最忙的前8个线程并打印堆栈 thread -n 8 -i 3000 : 列出3s内最忙的8个线程并打印堆栈(-i 为采样时间) thread -b :找出当前阻塞其他线程的线程 有时候我们发现应用卡住了, 通常是由于某个线程拿住了某个锁, 并且其他线程都在等待这把锁造成的。 为了排查这类问题, arthas提供了thread -b, 一键找出那个罪魁祸首。 注意, 目前只支持找出synchronized关键字阻塞住的线程, 如果是java.util.concurrent.Lock, 目前还不支持。

3. heapdump : dump java heap, 类似jmap命令的heap dump功能。

heapdump /tmp/dump.hprof : dump到指定文件 heapdump --live /tmp/dump.hprof : 只dump live对象

下载dump文件后,可以使用MAT查看,MAT官网下载: https://www.eclipse.org/mat/previousReleases.php ,主要要选择和本地一样的jvm版本,不然启动会失败。

使用MAT 分析 OOM 大内存问题,过程如下,是截取别的文章的过程。




image.png




image.png




image.png




image.png




image.png

4. watch: 观察到指定函数的调用情况。能观察到的范围为:返回值、抛出异常、入参

这个用于观察未打印日志的方法特别好用,包括入参 返参 和 异常

watch xxx.xxx.ABTestRecordServiceImpl doABTestWithLayer "{params,returnObj}" -x 3 -n 2 -x 指定输出结果的属性遍历深度,默认为 1,最大值是4 , 如果入参和出参是属性深度不一样(通常是不一样的,入参就是一个对象,出差会统一被一个Result包裹),需要分别设置才能观察到 params,returnObj : 指的是入参和返参,固定值 throwExp :观察异常信息 watch demo.MathGame primeFactors "{params,throwExp}" -e -x 2 -b : 在函数调用之前观察入参,因为入参有可能在执行被修改 -e :在函数异常之后观察 -s : 在函数返回之后观察,因为入参有可能在执行被修改 -n : 表示执行次数,即只打印n次,对于频繁调用来说,不设置的话,会打印很多 watch xxx.xxx.ABTestRecordServiceImpl doABTestWithLayer "{params,returnObj}" -x 3 -n 2 '#cost>100' '#cost>100' : 按照耗时过滤,在很多方法中都可以通用,表示只打印执行超过100ms的方法


image.png

实例应用:生产上一个已废弃的接口突然被调用,报了一个异常,由于是老接口,我们并没有catch捕获,导致我们的日志filter没能打印出入参来,我们想根据入参来定位是哪里在调用,是谁在调用,这时候就可以用 watch 来获取方法的调用入参。
发现是运营突然上线了一个很久都没用的活动导致的,我们直接下线就可以了。

5. trace: 渲染和统计整个调用链路上的所有性能开销和追踪调用链路。

trace命令只会匹配到的函数里的子调用,并不会向下trace多层。因为trace是代价比较贵的,多层trace可能会导致最终要trace的类和函数非常多。

trace xxx.DiscountCXOpenServiceImpl aaaRespCXDTOList '#cost > 50' -n 1 -n : 打印次数 '#cost>100' : 方法执行耗时 默认情况下,trace不会包含jdk里的函数调用,如果希望trace jdk里的函数,需要显式设置 --skipJDKMethod false。


image.png

6. stack:输出当前方法被调用的调用路径

如果一个方法被很多地方调用了,但是我们又不知道是被哪里调用时,可用这个命令查询

stack xxx.DiscountCacheUtil getStrategyCachaaa -n 1


image.png

7. profiler:生成应用热点的火焰图。

profiler start : 启动 启动时,默认采样的是cpu,可以通过 --event 来指定跟踪事件(cpu , alloc , lock ) profiler status :查看状态 profiler stop : 停止 停止时,默认生成html格式文件,可以通过 --file 指定生成路径和svg类型


image.png




image.png


从上面可以看出来耗时主要是在json parseArray格式化上。 横向长度越长,说明耗时越久

火焰图说明:火焰图是基于 perf 结果产生的 SVG 图片,用来展示 CPU 的调用栈。

  • y 轴表示调用栈,每一层都是一个函数。调用栈越深,火焰就越高,顶部就是正在执行的函数,下方都是它的父函数。

  • x 轴表示抽样数,如果一个函数在 x 轴占据的宽度越宽,就表示它被抽到的次数多,即执行的时间长。注意,x 轴不代表时间,而是所有的调用栈合并后,按字母顺序排列的。

火焰图就是看顶层的哪个函数占据的宽度最大。只要有“平顶”(plateaus),就表示该函数可能存在性能问题。

颜色没有特殊含义,因为火焰图表示的是 CPU 的繁忙程度,所以一般选择暖色调。

默认生成的是html格式,只是html格式找东西不方便





image.png

8. 定位问题

8.1 CPU过高问题

现象描述:运维突然打电话说是生成线上节点cpu高达80%,而且还在增加,但是最新的一个版本并没有什么复杂的功能上线,而且日志在报一个批量插入主键冲突的异常,但是这个批量插入的功能已经上线很久,并且在很多地方都有用到,所以不能定位到是哪里的问题,这时候可以用arthas来查找问题原因

dashboard -- 查看发现cpu高 不是GC引起的,占用CPU较多的线程只有一个 thread -n 6 -- 查看最繁忙的线程在执行的线程堆栈信息,然后可以直接定位具体代码行

8.2 TPS过低问题

现象描述:新上线一个高并发的复杂业务接口,压测的时候发现TPS只有50,明显是太低了,需要找出耗时较长的地方加以优化。

trace xxx.DiscountCXOpenServiceImpl aaaRespCXDTOList '#cost > 100' -n 1 由于trace命令只会匹配到的函数里的子调用,并不会向下trace多层,而这个业务接口很复杂,所以一层层找下去的话,太过于麻烦,所以用profiler 生成应用热点的火焰图来查找比较好, profiler start --event alloc //等待10s profiler stop --file /app/deploy/logs/profiler.svg


image.png

从上面的图中可以看出最终耗时比较久的竟然是 fastjson 的 parseArray方法,然后找到具体调用的地方后,
发现是因为内部缓存的原因,由于内部缓存用的公共方法,value为Stiring,所以每次getValue后,都需要parseArray 转化为List<Bean> ,之所以使用内部缓存就是因为value值太大,存redis时会造成网卡带宽不够,所以我们需要修改为自定义内部缓存,这样就可以避免 parseArray 方法,从而提高性能了。
private static ConcurrentHashMap<String, ConcurrentHashMap> cache = new ConcurrentHashMap<>();

这里其实还有一个问题,这种大对象频繁反序列化除了影响性能,还会每次都生成新的对象,导致在高并发下,内存也飙升。

参考文章:学会Arthas,让你3年经验掌握5年功力!

发布人:1db9****    IP:120.230.51.***     举报/删稿
展会推荐
让朕来说2句
评论
收藏
点赞
转发