java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Arthas排查Java程序线上问题

如何使用Arthas(阿尔萨斯)排查Java程序线上问题

作者:红衣女妖仙

Arthas是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,这篇文章主要介绍了如何使用Arthas(阿尔萨斯)排查Java程序线上问题的相关资料,需要的朋友可以参考下

前言:

Arthas(阿尔萨斯)是阿里巴巴开源的一款用于线上诊断 Java 程序的工具,通过全局视角实时查看应用程序加载、内存、垃圾回收和线程的状态等信息,并能在不修改程序代码和不中断程序运行的情况下,对程序运行问题进行排查,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载等信息,能够大大提升线上问题排查的效率。

通常,本地开发环境无法访问生产环境。如果在生产环境中遇到问题,则无法使用本地 IDE 远程调试(部分情况下可通过本地 IDE 远程 Debug 生产服务),并且,大部分情况下并不允许在生产环境中调试,因为它可能会影响业务,甚至中断程序。

一般情况下,若遇到生产问题,则会在测试环境中尝试复现生产问题,但某些问题在不同环境中不能轻易复现甚至不能复现。

故,若你想在生产环境中排查问题,尤其是 JVM 问题,那么不妨试试 Arthas,无需重启程序,无需修改代码,无需中断业务,如菲奥娜的被动 决斗之舞 般,可轻松发现正在运行的程序所漏出破绽。

1 使用场景

提示

以上所有问题,通过 Arthas 都可以解决!

2 下载安装

2.1 下载

2.1.1 从 maven 仓库下载

下载地址为 https://arthas.aliyun.com/download/latest_version?mirror=aliyun,下载文件为 zip 压缩包,下载后解压即可。

2.1.2 从 github relese 下载

下载地址为 https://github.com/alibaba/arthas/releases。

2.1.3 命令行下载

执行以下命令下载:

wget https://alibaba.github.io/arthas/arthas-boot.jar

# 或
# 推荐以此方式安装
curl -O https://arthas.aliyun.com/arthas-boot.jar

2.2 启动

2.2.1 用 as.sh 启动

解压后,执行文件夹内的 as.sh 脚本文件启动,命令如下:

./as.sh
# 或
./as.sh -h   # -h 可打印帮助信息

2.2.2 用 arthsa-boot 启动

arthas 的启动实际上是执行 arthas-boot.jar jar 包,解压后,文件夹内有 arthas-boot.jar,直接使用以下命令启动:

java -jar arthas-boot.jar

3 快速入门

3.1 启动 arthas

使用 java -jar arthas-boot.jar 命令启动 arthas 程序后会输出以下内容,其中 1 2 3 4 5 编号所标识的 java 进程则是当前可监测的正在运行的 java 程序。

⚠️注意

请注意,在使用 java -jar arthas-boot.jar 命令启动 arthas 时,当前用户需要和目标进程的启动用户保持一致,否则可能会 attach(附加)失败。若 attach 不上目标进程,则可查看 ~/logs/arthas/ 目录下的日志。

编号 4 所标识的 UserCenterApplication 程序则是此次的 demo,输入 4 再回车后,arthas 便会附加到目标进程上,并输出相关日志:

3.2 查看进程信息

可通过 dashboard 命令查看当前进程对应控制面板,即展示当前进程的实时信息,包括线程的名称、运行状态、CPU 占用等信息,内存信息,运行时环境等信息。按 ctrl + c 可中断执行。

关于 dashboard 命令的详细信息将在下文进行说明。

3.3 查看线程堆栈

通过 thread 命令加线程 ID 即可查看某个线程的当前堆栈信息。

3.4 反编译类

通过 jad 命令加全类名,即可查看某个已加载类的反编译信息。

3.5 退出 arthas

如果只退出针对当前进程的连接,则使用 exitquit 即可,执行后 arthas 依旧会 attach 到目标进程上,端口会保持开放,下次连接时可直接连接上。若想完全退出 arthas,则执行 stop 命令即可。

4 命令列表

4.1 基础命令

4.2 jvm 相关

4.3 class/classloader 相关

4.4 monitor/watch/trace 相关

⚠️注意

请注意,这些命令都是通过字节码增强技术来实现的,会在指定类的方法中插入一些切面来实现数据统计和观测,因此在线上、预发使用时,请尽量明确需要观测的类、方法以及条件,诊断结束要执行 stop 或将增强过的类执行 reset 命令。

4.5 profiler/火焰图

4.6 后台异步任务

当线上出现偶发问题,比如需要 watch 某个条件,而这个条件一天可能才会出现一次时,则可以使用此类命令。

5 常用命令

5.1 dashboard

查看当前进程对应控制面板,即展示当前进程的实时信息,包括线程的名称、运行状态、cpu 占用等信息,内存信息,运行时环境等信息。按 ctrl + c 可中断执行。

参数说明:

数据说明:

Java 8 之后支持获取 JVM 内部线程 cpu 时间。JVM 内部线程如:

截图展示:

5.2 memory

查看 JVM 内存信息,具体字段信息可参考:

截图展示:

5.3 thread

查看当前进程中某个线程的堆栈信息。如 thread 45,其中 45 为线程 ID。

参数说明:

提示

这里的 cpu 使用率与 linux 命令 top -H -p <pid> 的线程 %CPU 类似,一段采样间隔时间内,当前 jvm 里各个线程的增量 cpu 时间与采样间隔时间的比例。

工作原理:

⚠️注意

这个统计也会产生一定的开销(JDK 这个借口本身开销比较大),因此会看到 as 的线程占用一定的百分比,为了降低统计自身的开销所带来的影响,建议拉长采样间隔时间,比如 5000ms。

截图展示:

5.4 vmtool

利用 JVMTI 接口,实现查询内存对象,强制 GC 等功能。JVMTI 文档见 https://docs.oracle.com/javase/8/docs/platform/jvmti/jvmti.html。

参数说明:

查询对象截图展示:

其它功能:

5.5 jad

查看已加载到 jvm 中的类的源码的反编译信息。通过查看反编译后的 java 代码,便于分析代码逻辑,以及确认发布后的代码是否为你修改的代码。

参数说明:

截图展示:

5.6 retransform

加载外部的 .class 文件,retransform jvm 已加载的类,即热更新类,这个功能非常有用!

热更新的操作步骤是什么呢?首先修改目标类,然后将目标类转换成 .class 文件,最后再热更新,这一系列操作都可以通过相关命令实现。那如果我们要修改的内容很少,直接 vim 就可以修改,那么它的具体操作可以是这样:

提示

若多次执行 retransform 加载同一个 class 文件,则会有多条 retransform entry

针对 retransform entry 的操作:

消除 retransform 的影响:若对某个类执行 retransform 之后,想消除影响,则需要:

提示

若不清楚掉所有的 retransform entry,并重新出发 retransform,则 stop 时,retransform 过的类仍然生效。

retransform 的限制:

⚠️注意

redefine 命令与 retransform 命令功能类似,但建议使用后者。

5.7 sc 与 sm

search class 的简写,查看所有已加载到 jvm 中的 class 的信息。

参数说明:

截图展示:

⚠️注意

smsc 命令大同小异,需要注意的是 sm 命令只能看到由当前类所定义的方法,父类的则看不到。

5.8 stack

查看当前方法被调用的调用路径。

参数说明:

⚠️注意

这里重点要说明的是观察表达式,观察表达式的构成主要由 ognl 表达式组成,所以你可以这样写 {params, returnObj},只要是一个合法的 ognl 表达式,都能被正常支持。

观察的维度也比较多,主要体现在参数 advice 的数据结构上。Advice 参数最主要是封装了通知节点的所有信息。

截图展示:

5.9 trace

查看方法内部调用路径,并输出方法路径上每个节点的耗时。该命令会主动搜索 class-pattern / method-pattern 对应的方法调用路径,渲染和统计整个调用链路上的所有性能开销和追踪调用链路。

参数说明:

⚠️注意

重点说明条件表达式,条件表达式主要由 ognl 表达式组成,所以你可以这样写 params[0]<0,只要是合法的 ognl 表达式,都能被正常支持。

很多时候我们可能只想看到某个方法的 rt 大于某个时间之后的 trace 结果,巧的是 arthas 可以按照方法执行耗时来过滤了,比如你可以这样写 trace *StringUtils isBlank '#cost>100',表示当该方法的执行超过 100ms 时才会输出 trace 的结果。不得不说,这个功能太牛了。

提示

stack/trace/watch 这三个命令都支持 #cost 参数。

截图展示:

其中每个方法前的结果表示该方法在此次调用链路中耗时所占百分比和耗时,方法后面的 #num(如 #62)表示该方法在源文件的第 num 行被调用。

5.10 watch

可观测指定函数的调用情况,如入参、返回值、抛出异常等信息,且支持 ognl 表达式。

⚠️注意

下面有一个与 watch 命令功能相似的命令叫 tt,二者的区别是 watch 虽然很方便灵活,但需要提前想清楚观察表达式的拼写,这对排查问题而言要求太高,且很多时候我们并不知道问题出自何方,只能靠蛛丝马迹进行猜测,但是如果能记录下当时方法调用的所有入参和返回值、抛出的异常等信息,那将对整个问题的思考和排查有很大帮助,没错儿,tt 命令的功能就是这个。

很明显,当我想到写这个醒目的⚠️时,我心思就早已飘到 tt 去了。

5.11 tt

方法执行数据的时空隧道,记录下指定方法每次调用的入参、返回值和异常等信息,并能对这些不同时间下的调用进行观测。

‼️警告

tt 命令的实现原理是:将函数的入参/返回值等信息,保存到一个 Map<Integer, TimeFragment> 中,该 map 的默认容量大小是 100。

tt 相关功能在使用完之后,需要手动释放内存,否则长时间可能会导致 OOM,且即使退出 athas 也不会自动清除 tt 的缓存 map

参数说明:

记录调用:tt -t org.xgllhz.usercenter.blog.admin.service.impl.BlogServiceImpl listBlogPage,结果如下:

字段说明:

查看某次调用信息:tt -i 1000,结果如下:

最后别忘了用 tt --delete-all 将所有记录都清除,否则会 OOM。

总结

到此这篇关于如何使用Arthas(阿尔萨斯)排查Java程序线上问题的文章就介绍到这了,更多相关Arthas排查Java程序线上问题内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文