大家好,我是Yuan,今天给大家介绍一款调优神器 -- 阿里巴巴Arthas,可以帮助你的应用释放潜力。
阿里巴巴 Arthas 是一个诊断工具,可以用于监视、分析和解决 Java 应用程序的问题。使用 Arthas 的一个主要优点是,我们不需要修改代码,甚至不需要重新启动我们想要监视的 Java 服务。
在本教程中,我们将首先安装 Arthas,在此之后,通过一个简单的案例来演示 Arthas 的一些关键特性。
最后,由于 Arthas 是用 Java 编写的,因此它是跨平台的,可以在 Linux、macOS 和 Windows 上运行。
首先,我们可以通过直接下载链接或使用curl来下载 Arthas 库:
curl -O https://alibaba.github.io/arthas/arthas-boot.jar
现在,让我们通过运行带有-h(帮助)选项的 Arthas 来测试它是否工作:
java -jar arthas-boot.jar -h
如果成功,我们应该看到显示所有命令的帮助指南:
在本教程中,我们将使用一个非常简单的应用程序,基于利用递归实现的斐波那契数列的相对低效的实现方式:
public class FibonacciGenerator {
public static void main(String[] args) {
System.out.println("按任意键继续");
System.in.read();
for (int i = 0; i < 100; i++) {
long result = fibonacci(i);
System.out.println(format("fib(%d): %d", i, result));
}
}
public static long fibonacci(int n) {
if (n == 0 || n == 1) {
return 1L;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
}
这个示例的最有趣的部分是遵循斐波那契数列的数学定义的 fibonacci 方法。
在 main 方法中,我们使用一个循环和相对较大的数字,以便让计算机进行较长时间的计算。这当然正是我们想要的,以便演示 Arthas。
现在让我们试试 Arthas!我们需要做的第一件事是运行我们的小型斐波那契应用程序。我们可以使用我们喜欢的 IDE 或直接在终端中运行它。它会要求按下一个键才能启动。我们将在将进程附加到 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 附加到进程后,我们现在可以按下一个键,程序将开始打印斐波那契数。
一旦 Arthas 启动,我们可以使用仪表盘。在这种情况下,我们通过输入 "dashboard" 命令来使用仪表盘。现在,我们可以看到一个详细的屏幕,其中包含多个面板和关于我们的 Java 进程的许多信息:
让我们更详细地看一下其中的一些内容:
我们可以通过按下 "q" 键退出仪表盘。
我们应该记住,即使退出,Arthas 仍会附加到我们的进程上。因此,为了正确地从我们的进程中断开它的连接,我们需要运行 "stop" 命令。
在仪表盘中,我们看到我们的主进程占用了几乎 100% 的 CPU。该进程的 ID 是 1,在第一列中可以看到。
现在我们已经退出了仪表盘,我们可以通过运行 "thread" 命令来更详细地分析该进程:
thread 1
作为参数传递的数字是线程 ID。Arthas 打印出一个堆栈跟踪信息,其中充斥着对 fibonacci 方法的调用。
如果堆栈跟踪信息很长而且难以阅读,可以使用 "thread" 命令结合 "grep" 命令来过滤:
thread 1 | grep 'main('
这将只打印与 "grep" 命令匹配的行:
[arthas@25500]$ thread 1 | grep 'main('
at com.baeldung.arthas.FibonacciGenerator.main(FibonacciGenerator.java:10)
假设我们正在分析一个我们对其中了解甚少或一无所知的Java应用程序,突然发现堆栈中充斥着以下类型的重复调用:
[arthas@59816]$ thread 1
"main" Id=1 RUNNABLE
at app//com.baeldung.arthas.FibonacciGenerator.fibonacci(FibonacciGenerator.java:18)
at app//com.baeldung.arthas.FibonacciGenerator.fibonacci(FibonacciGenerator.java:18)
...
由于我们运行了Arthas,我们可以反编译一个类来查看其内容。为了实现这一点,我们可以使用jad命令,将限定类名作为参数传递:
jad com.baeldung.arthas.FibonacciGenerator
类加载器:
+-jdk.internal.loader.ClassLoaders $ AppClassLoader @ 799f7e29
+-jdk.internal.loader.ClassLoaders $ PlatformClassLoader @ 60f1dd34
位置:
/home/amoreno/work/baeldung/tutorials/libraries-3/target/
/*
* 反编译使用CFR。
*/
package com.baeldung.arthas;
import java.io.IOException;
import java.io.InputStream;
importjava.io.PrintStream;
public class FibonacciGenerator {
public static void main(String[] arrstring) throws IOException {
输出是反编译的Java类和一些有用的元数据,如类的位置。这是一个非常有用和强大的功能。
搜索类命令在搜索JVM中加载的类时非常方便。我们可以使用它通过输入sc并将模式作为参数传递来使用,带或不带通配符:
[arthas@70099]$ sc *Fibonacci*
com.baeldung.arthas.FibonacciGenerator
Affect(row-cnt:1) cost in 5 ms.
一旦我们获得了类的限定名称,我们可以使用两个附加标志来查找更多信息:
然而,类的字段必须与详细信息一起查询:
[arthas@70099]$ sc -df com.baeldung.arthas.FibonacciGenerator
class-info com.baeldung.arthas.FibonacciGenerator
...
同样,我们可以使用sm(搜索方法)命令来查找类中加载的方法。在这种情况下,对于我们的类com.baeldung.arthas.FibonacciGenerator,我们可以运行:
[arthas@70099]$ sm com.baeldung.arthas.FibonacciGenerator
com.baeldung.arthas.FibonacciGenerator ()V
com.baeldung.arthas.FibonacciGenerator main([Ljava/lang/String;)V
com.baeldung.arthas.FibonacciGenerator fibonacci(I)J
Affect(row-cnt:3) cost in 4 ms.
我们可以使用-d标志来检索方法的详细信息。最后,我们可以传递方法的名称作为可选参数,以缩小返回方法的数量:
sm -d com.baeldung.arthas.FibonacciGenerator fibonacci
declaring-class com.baeldung.arthas.FibonacciGenerator
method-name fibonacci
modifier public,static
annotation
parameters int
return long
exceptions
classLoaderHash 799f7e29
我们可以使用Arthas来监视方法,这在调试应用程序的性能问题时非常方便。为此,我们可以使用monitor命令。
monitor命令需要一个-c <秒数>标志和两个参数 - 限定类名和方法名。
对于我们的案例研究,让我们来调用monitor:
monitor -c 10 com.baeldung.arthas.FibonacciGenerator fibonacci
正如我们所预期的,Arthas将每10秒打印有关fibonacci方法的指标:
Affect(class-cnt:1 , method-cnt:1) cost in 47 ms.
timestamp class method total success fail avg-rt(ms) fail-rate
-----------------------------------------------------------------------------------------------------------------------------
2020-03-07 1126 com.baeldung.arthas.FibonacciGenerator fibonacci 528957 528957 0 0.07 0.00%
...
对于那些最终失败的调用,我们也有指标 - 这对于调试很有用。
如果我们需要调试方法的参数,我们可以使用watch命令。但是,语法会稍微复杂一些:
watch com.baeldung.arthas.FibonacciGenerator fibonacci '{params[0], returnObj}' 'params[0]>10' -n 10
让我们详细看一下各个参数:
对于此示例,我们只想在参数大于10时监视。最后,我们添加一个标志来限制结果为10个:
watch com.baeldung.arthas.FibonacciGenerator fibonacci '{params[0], returnObj}' 'params[0]>10' -n 10
按Q或Ctrl+C中断。
Affect(class-cnt:1 , method-cnt:1) cost in 19 ms.
ts=2020-02-17 2108; [cost=30.165211ms] result=@ArrayList[
@Integer[11],
@Long[144],
]
ts=2020-02-17 2108; [cost=50.405506ms] result=@ArrayList[
@Integer[12],
@Long[233],
]
...
在这里,我们可以看到带有CPU时间和输入/返回值的调用示例。
对于那些对应用程序性能感兴趣的人来说,通过分析器命令提供了一种非常直观的能力。分析器将评估我们的进程正在使用的CPU的性能。
让我们通过运行profiler start来启动分析器。这是一个非阻塞的任务,意味着在分析器工作时我们可以继续使用Arthas。
随时可以通过运行profiler getSamples来询问分析器有多少个样本。
现在让我们使用profiler stop来停止分析器。此时,一个FlameGraph图像将被保存。在这个具体的案例中,我们有一个以斐波那契线程为主导的图表:
注意,当我们想要检测我们的CPU时间花在哪里时,这个图表特别有用。
在本教程中,我们探索了Arthas的一些最强大和有用的功能。
正如我们所见,Arthas有许多命令可以帮助我们诊断各种问题。当我们无法访问正在审查的应用程序的代码,或者我们想快速诊断在服务器上运行的有问题的应用程序时,它也可以特别有帮助。
全部0条评论
快来发表一下你的评论吧 !