学会 Arthas!让你 3 年经验掌握 5 年功力

点击下方名片,设为星标

回复“1024”获取2TB学习资源!

大家好,我是民工哥,今天给大家介绍一款调优神器 -- 阿里巴巴Arthas,可以帮助你的应用释放潜力。

979d73ce1e5faa03588e7030b2aa020e.png

介绍

阿里巴巴 Arthas 是一个诊断工具,可以用于监视、分析和解决 Java 应用程序的问题。使用 Arthas 的一个主要优点是,我们不需要修改代码,甚至不需要重新启动我们想要监视的 Java 服务。

在本教程中,我们将首先安装 Arthas,在此之后,通过一个简单的案例来演示 Arthas 的一些关键特性。

最后,由于 Arthas 是用 Java 编写的,因此它是跨平台的,可以在 Linux、macOS 和 Windows 上运行。

使用场景

  • 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?

  • 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?

  • 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?

  • 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!

  • 是否有一个全局视角来查看系统的运行状况?

  • 有什么办法可以监控到 JVM 的实时运行状态?

  • 怎么快速定位应用的热点,生成火焰图?

  • 怎样直接从 JVM 内查找某个类的实例?

Arthas 支持 JDK 6+,支持 Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。

下载和入门

首先,我们可以通过直接下载链接或使用curl来下载 Arthas 库:

curl -O https://alibaba.github.io/arthas/arthas-boot.jar

现在,让我们通过运行带有-h(帮助)选项的 Arthas 来测试它是否工作:

java -jar arthas-boot.jar -h

如果成功,我们应该看到显示所有命令的帮助指南:9d8e81e9a1922f64d891fe29b93ad633.png更多安装细节:https://arthas.aliyun.com/doc/install-detail.html

具体使用

启动 Arthas

现在,让我们运行 Arthas 可执行文件:

java -jar arthas-boot.jar

Arthas 提示选择要附加到的进程:

[INFO] arthas-boot version: 3.1.7
[INFO] Found existing java process, please choose one and hit RETURN.
* [1]: 25500 com.baeldung.arthas.FibonacciGenerator
...

让我们选择名称为 com.baeldung.arthas.FibonacciGenerator 的进程。在此示例中,只需在列表中输入数字‘1’并按 Enter 即可。

Arthas 现在会附加到该进程并启动:

[INFO] Try to attach process 25500
[INFO] Attach process 25500 success.
...

一旦 Arthas 启动,我们就有一个提示符,可以发出不同的命令。我们可以使用 help 命令获取有关可用选项的更多信息。为了方便使用 Arthas,我们还可以使用 tab 键来自动完成其命令。

仪表盘

一旦 Arthas 启动,我们可以使用仪表盘。在这种情况下,我们通过输入 "dashboard" 命令来使用仪表盘。现在,我们可以看到一个详细的屏幕,其中包含多个面板和关于我们的 Java 进程的许多信息:e4269bfeaa4693bfed483d96ac83706e.png

参数说明
ID  #Java 级别的线程 ID,注意这个 ID 不能跟 jstack 中的 nativeID 一一对应。
NAME  #线程名
GROUP  #线程组名
PRIORITY  #线程优先级, 1~10 之间的数字,越大表示优先级越高
STATE  #线程的状态
CPU%  #线程的 cpu 使用率。比如采样间隔 1000ms,某个线程的增量 cpu 时间为 100ms,则 cpu 使用率=100/1000=10%
DELTA_TIME  #上次采样之后线程运行增量 CPU 时间,数据格式为秒
TIME#线程运行总 CPU 时间,数据格式为分:秒
INTERRUPTED  #线程当前的中断位状态
DAEMON  #是否是 daemon 线程

分析器

profiler 命令支持生成应用热点的火焰图。本质上是通过不断的采样,然后把收集到的采样结果生成火焰图。

profiler 命令基本运行结构是 profiler action [actionArg]

参数说明

27efd7d05fdb61a323b37c8ded2769c2.png启动分析器

$ profiler start
Started [cpu] profiling
#默认情况下,生成的是 cpu 的火焰图,即 event 为cpu。可以用--event参数来指定。
通过浏览器查看 arthas-output 下面的 profiler 结果

默认情况下,arthas 使用 3658 端口,则可以打开:http://localhost:3658/arthas-output/查看到arthas-output目录下面的 profiler 结果:68bf28cd66ec33dfece4c9cdf545f123.png点击可以查看具体的结果:e7655ab464bd9f2a3a6b90b65c4de76b.png

容器相关

启动arthas-boot来进行诊断

$ docker exec -it math-game /bin/sh -c "java -jar /opt/arthas/arthas-boot.jar"
* [1]: 9 jar[INFO] arthas home: /opt/arthas
[INFO] Try to attach process 9
[INFO] Attach process 9 success.
[INFO] arthas-client connect 127.0.0.1 3658
,---.  ,------. ,--------.,--.  ,--.  ,---.   ,---.
/  O  \ |  .--. ''--.  .--'|  '--'  | /  O  \ '   .-'
|  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |`.  `-.
|  | |  ||  |\  \    |  |   |  |  |  ||  | |  |.-'    |
`--' `--'`--' '--'   `--'   `--'  `--'`--' `--'`-----'wiki: https://arthas.aliyun.com/doc
version: 3.0.5
pid: 9
time: 2018-12-18 11:30:36

诊断 Docker 里的 Java 进程

docker exec -it  ${containerId} /bin/bash -c "wget https://arthas.aliyun.com/arthas-boot.jar && java -jar arthas-boot.jar"

诊断 k8s 里容器里的 Java 进程

kubectl exec -it ${pod} --container ${containerId} -- /bin/bash -c "wget https://arthas.aliyun.com/arthas-boot.jar && java -jar arthas-boot.jar"

把 Arthas 安装到基础镜像里 可以很简单把 Arthas 安装到你的 Docker 镜像里。

FROM openjdk:8-jdk-alpine# copy arthas
COPY --from=hengyunabc/arthas:latest /opt/arthas /opt/arthas

如果想指定版本,可以查看具体的 tags:https://hub.docker.com/r/hengyunabc/arthas/tags

分析堆栈跟踪

thread 用来查看当前线程信息,查看线程的堆栈。69282e106aadfb6471868e7536fe08bc.png当没有参数时,显示第一页线程的信息,默认按照 CPU 增量时间降序排列,只显示第一页数据。

$ thread
Threads Total: 33, NEW: 0, RUNNABLE: 9, BLOCKED: 0, WAITING: 3, TIMED_WAITING: 4, TERMINATED: 0, Internal threads: 17
ID   NAME                           GROUP          PRIORITY  STATE     %CPU      DELTA_TIME TIME      INTERRUPT DAEMON
-1   C2 CompilerThread0             -              -1        -         5.06      0.010      0:0.973   false     true
-1   C1 CompilerThread0             -              -1        -         0.95      0.001      0:0.603   false     true
23   arthas-command-execute         system         5         RUNNABLE  0.17      0.000      0:0.226   false     true
-1   VM Periodic Task Thread        -              -1        -         0.05      0.000      0:0.094   false     true
-1   Sweeper thread                 -              -1        -         0.04      0.000      0:0.011   false     true
-1   G1 Young RemSet Sampling       -              -1        -         0.02      0.000      0:0.025   false     true
12   Attach Listener                system         9         RUNNABLE  0.0       0.000      0:0.022   false     true
11   Common-Cleaner                 InnocuousThrea 8         TIMED_WAI 0.0       0.000      0:0.000   false     true
3    Finalizer                      system         8         WAITING   0.0       0.000      0:0.000   false     true
2    Reference Handler              system         10        RUNNABLE  0.0       0.000      0:0.000   false     true
4    Signal Dispatcher              system         9         RUNNABLE  0.0       0.000      0:0.000   false     true
15   arthas-NettyHttpTelnetBootstra system         5         RUNNABLE  0.0       0.000      0:0.029   false     true
22   arthas-NettyHttpTelnetBootstra system         5         RUNNABLE  0.0       0.000      0:0.196   false     true
24   arthas-NettyHttpTelnetBootstra system         5         RUNNABLE  0.0       0.000      0:0.038   false     true
16   arthas-NettyWebsocketTtyBootst system         5         RUNNABLE  0.0       0.000      0:0.001   false     true
17   arthas-NettyWebsocketTtyBootst system         5         RUNNABLE  0.0       0.000      0:0.001   false     true

thread --all显示所有匹配的线程,显示所有匹配线程信息,有时需要获取全部 JVM 的线程数据进行分析。

thread id显示指定线程的运行堆栈

$ thread 1
"main" Id=1 WAITING on java.util.concurrent.CountDownLatch$Sync@29fafb28at sun.misc.Unsafe.park(Native Method)-  waiting on java.util.concurrent.CountDownLatch$Sync@29fafb28at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:997)at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1304)at java.util.concurrent.CountDownLatch.await(CountDownLatch.java:231)

thread --state 查看指定状态的线程

[arthas@28114]$ thread --state WAITING
Threads Total: 16, NEW: 0, RUNNABLE: 9, BLOCKED: 0, WAITING: 3, TIMED_WAITING: 4, TERMINATED: 0
ID   NAME                           GROUP           PRIORITY   STATE     %CPU      DELTA_TIME TIME      INTERRUPTE DAEMON
3    Finalizer                      system          8          WAITING   0.0       0.000      0:0.000   false      true
20   arthas-UserStat                system          9          WAITING   0.0       0.000      0:0.001   false      true
14   arthas-timer                   system          9          WAITING   0.0       0.000

jvm

查看当前 JVM 信息

$ jvm
RUNTIME
--------------------------------------------------------------------------------------------------------------MACHINE-NAME                   37@ff267334bb65JVM-START-TIME                 2020-07-23 07:50:36MANAGEMENT-SPEC-VERSION        1.2SPEC-NAME                      Java Virtual Machine SpecificationSPEC-VENDOR                    Oracle CorporationSPEC-VERSION                   1.8VM-NAME                        Java HotSpot(TM) 64-Bit Server VMVM-VENDOR                      Oracle CorporationVM-VERSION                     25.201-b09INPUT-ARGUMENTS                []CLASS-PATH                     demo-arthas-spring-boot.jarBOOT-CLASS-PATH                /usr/lib/jvm/java-8-oracle/jre/lib/resources.jar:/usr/lib/jvm/java-8-oracle/jre/lib/rt.jar:/usr/lib/jvm/java-8-oracle/jre/lib/sunrsasign.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jsse.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jce.jar:/usr/lib/jvm/java-8-oracle/jre/lib/charsets.jar:/usr/lib/jvm/java-8-oracle/jre/lib/jfr.jar:/usr/lib/jvm/java-8-oracle/jre/classesLIBRARY-PATH                   /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib--------------------------------------------------------------------------------------------------------------CLASS-LOADING
--------------------------------------------------------------------------------------------------------------LOADED-CLASS-COUNT             7529TOTAL-LOADED-CLASS-COUNT       7529UNLOADED-CLASS-COUNT           0IS-VERBOSE                     false--------------------------------------------------------------------------------------------------------------COMPILATION
--------------------------------------------------------------------------------------------------------------NAME                           HotSpot 64-Bit Tiered CompilersTOTAL-COMPILE-TIME             14921(ms)--------------------------------------------------------------------------------------------------------------GARBAGE-COLLECTORS
--------------------------------------------------------------------------------------------------------------PS Scavenge                            name : PS Scavenge[count/time (ms)]                      collectionCount : 7collectionTime : 68PS MarkSweep                           name : PS MarkSweep[count/time (ms)]                      collectionCount : 1collectionTime : 47--------------------------------------------------------------------------------------------------------------MEMORY-MANAGERS
--------------------------------------------------------------------------------------------------------------CodeCacheManager               Code CacheMetaspace Manager              MetaspaceCompressed Class SpaceCopy                           Eden SpaceSurvivor SpaceMarkSweepCompact               Eden SpaceSurvivor SpaceTenured Gen--------------------------------------------------------------------------------------------------------------MEMORY
--------------------------------------------------------------------------------------------------------------HEAP-MEMORY-USAGE                      init : 268435456(256.0 MiB)[memory in bytes]                      used : 18039504(17.2 MiB)committed : 181403648(173.0 MiB)max : 3817865216(3.6 GiB)NO-HEAP-MEMORY-USAGE                   init : 2555904(2.4 MiB)[memory in bytes]                      used : 33926216(32.4 MiB)committed : 35176448(33.5 MiB)max : -1(-1 B)--------------------------------------------------------------------------------------------------------------OPERATING-SYSTEM
--------------------------------------------------------------------------------------------------------------OS                             LinuxARCH                           amd64PROCESSORS-COUNT               3LOAD-AVERAGE                   29.53VERSION                        4.15.0-52-generic--------------------------------------------------------------------------------------------------------------THREAD
--------------------------------------------------------------------------------------------------------------COUNT                          30DAEMON-COUNT                   24PEAK-COUNT                     31STARTED-COUNT                  36DEADLOCK-COUNT                 0--------------------------------------------------------------------------------------------------------------FILE-DESCRIPTOR
--------------------------------------------------------------------------------------------------------------MAX-FILE-DESCRIPTOR-COUNT      1048576OPEN-FILE-DESCRIPTOR-COUNT     100
Affect(row-cnt:0) cost in 88 ms.

memory

查看 JVM 内存信息。

$ memory
Memory                           used      total      max        usage
heap                             32M       256M       4096M      0.79%
g1_eden_space                    11M       68M        -1         16.18%
g1_old_gen                       17M       184M       4096M      0.43%
g1_survivor_space                4M        4M         -1         100.00%
nonheap                          35M       39M        -1         89.55%
codeheap_'non-nmethods'          1M        2M         5M         20.53%
metaspace                        26M       27M        -1         96.88%
codeheap_'profiled_nmethods'     4M        4M         117M       3.57%
compressed_class_space           2M        3M         1024M      0.29%
codeheap_'non-profiled_nmethods' 685K      2496K      120032K    0.57%
mapped                           0K        0K         -          0.00%
direct                           48M       48M        -          100.00%

监视方法调用

我们可以使用Arthas来监视方法,这在调试应用程序的性能问题时非常方便。为此,我们可以使用monitor命令。bd751217990b53472bb46b9978d46e1b.pngmonitor命令需要一个-c <秒数>标志和两个参数 - 限定类名和方法名。

$ monitor -c 5 demo.MathGame primeFactors
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 94 ms.timestamp            class          method        total  success  fail  avg-rt(ms)  fail-rate
-----------------------------------------------------------------------------------------------2018-12-03 19:06:38  demo.MathGame  primeFactors  5      1        4     1.15        80.00%timestamp            class          method        total  success  fail  avg-rt(ms)  fail-rate
-----------------------------------------------------------------------------------------------2018-12-03 19:06:43  demo.MathGame  primeFactors  5      3        2     42.29       40.00%timestamp            class          method        total  success  fail  avg-rt(ms)  fail-rate
-----------------------------------------------------------------------------------------------2018-12-03 19:06:48  demo.MathGame  primeFactors  5      3        2     67.92       40.00%timestamp            class          method        total  success  fail  avg-rt(ms)  fail-rate
-----------------------------------------------------------------------------------------------2018-12-03 19:06:53  demo.MathGame  primeFactors  5      2        3     0.25        60.00%timestamp            class          method        total  success  fail  avg-rt(ms)  fail-rate
-----------------------------------------------------------------------------------------------2018-12-03 19:06:58  demo.MathGame  primeFactors  1      1        0     0.45        0.00%timestamp            class          method        total  success  fail  avg-rt(ms)  fail-rate
-----------------------------------------------------------------------------------------------2018-12-03 19:07:03  demo.MathGame  primeFactors  2      2        0     3182.72     0.00%
f1017c1973e0887a416a215c053c1756.png

监控方法参数

可以监测一个方法的入参和返回值。有些问题线上会出现,本地重现不了,这时这个命令就有用了。37d7db7e8b7d4dcc0d1987161957ad92.png条件表达式的例子

$ watch demo.MathGame primeFactors "{params[0],target}" "params[0]<0"
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 68 ms.
ts=2018-12-03 19:36:04; [cost=0.530255ms] result=@ArrayList[@Integer[-18178089],@MathGame[demo.MathGame@41cf53f9],
]

更多参考:https://arthas.aliyun.com/doc/watch.html

命令列表

基础命令

base64 #base64 编码转换,和 linux 里的 base64 命令类似
cat #打印文件内容,和 linux 里的 cat 命令类似
cls #清空当前屏幕区域
echo #打印参数,和 linux 里的 echo 命令类似
grep #匹配查找,和 linux 里的 grep 命令类似
help #查看命令帮助信息
history #打印命令历史
keymap #Arthas 快捷键列表及自定义快捷键
pwd #返回当前的工作目录,和 linux 命令类似
quit #退出当前 Arthas 客户端,其他 Arthas 客户端不受影响
reset #重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所有增强过的类
session #查看当前会话的信息
stop #关闭 Arthas 服务端,所有 Arthas 客户端全部退出
tee #复制标准输入到标准输出和指定的文件,和 linux 里的 tee 命令类似
version #输出当前目标 Java 进程所加载的 Arthas 版本号

jvm 相关

dashboard #当前系统的实时数据面板
getstatic #查看类的静态属性
heapdump #dump java heap, 类似 jmap 命令的 heap dump 功能
jvm #查看当前 JVM 的信息
logger #查看和修改 logger
mbean  #查看 Mbean 的信息
memory #查看 JVM 的内存信息
ognl  #执行 ognl 表达式
perfcounter #查看当前 JVM 的 Perf Counter 信息
sysenv #查看 JVM 的环境变量
sysprop #查看和修改 JVM 的系统属性
thread #查看当前 JVM 的线程堆栈信息
vmoption #查看和修改 JVM 里诊断相关的 option
vmtool #从 jvm 里查询对象,执行 forceGc

class/classloader 相关

classloader #查看 classloader 的继承树,urls,类加载信息,使用 classloader 去 getResource
dump #dump 已加载类的 byte code 到特定目录
jad  #反编译指定已加载类的源码
mc   #内存编译器,内存编译.java文件为.class文件
redefine  #加载外部的.class文件,redefine 到 JVM 里
retransform  #加载外部的.class文件,retransform 到 JVM 里
sc #查看 JVM 已加载的类信息
sm #查看已加载类的方法信息

monitor/watch/trace 相关

monitor #方法执行监控
stack #输出当前方法被调用的调用路径
trace #方法内部调用路径,并输出方法路径上的每个节点上耗时
tt #方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测
watch #方法执行数据观测

总结

在本教程中,我们探索了Arthas的一些最强大和有用的功能。

正如我们所见,Arthas有许多命令可以帮助我们诊断各种问题。当我们无法访问正在审查的应用程序的代码,或者我们想快速诊断在服务器上运行的有问题的应用程序时,它也可以特别有帮助。

参考资料:

  • 官方文档:https://arthas.aliyun.com/doc/

  • Arthas的GitHub仓库地址:https://github.com/alibaba/arthas

读者专属技术群

构建高质量的技术交流社群,欢迎从事后端开发、运维技术进群(备注岗位,已在技术交流群的请勿重复添加)。主要以技术交流、内推、行业探讨为主,请文明发言。广告人士勿入,切勿轻信私聊,防止被骗。

扫码加我好友,拉你进群

23981b547b45a85313067079bbc90db7.jpeg

推荐阅读 点击标题可跳转

36 张图,一次性补全你的网络知识短板!

面试官:如何在 Docker 容器中抓包?问倒一大片

又一款轻量级监控利器!开源了

去了一家不到20人的IT公司后,真的是大开眼界

目前工资最高的外包公司汇总(2023最新版)!

卸载 Postman!事实证明,它更牛逼。。。

果真有这样的公司,够横!直接干上了热搜

843c4d818c63be1efd6864fb5d1e9911.png

PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下在看,加个星标,这样每次新文章推送才会第一时间出现在你的订阅列表里。点在看支持我们吧!


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部