目录

1 arthas介绍

1.1 简介

1.2 背景

1.3 Arthas(阿尔萨斯)能为你做什么?

2 window环境搭建

2.1 下载和启动

2.1 启动后:选择需要监控的服务

3 快速入门

3.1 打开浏览器

3.2 开启trace请求

3.3  查看 dashboard

3.6. watch

3.7. 退出 arthas

4 进阶使用

4.1 通过浏览器连接 arthas

4.2 scrollback URL 参数

4.3 使用 arthas tunnel server

其余参考官网

5 idea插件arthas idea

5.1 Arthas-idea(部分命令可视化)

5.2 Alibaba Cloud Toolkit 热部署组件(一键 retransform)

5.3 安装插件

6 相同功能工具介绍【skywalking】

1.1 概念

1.2 功能列表

1.3 整体架构



arthas官网

1 arthas介绍

1.1 简介

img

Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。

1.2 背景

通常,本地开发环境无法访问生产环境。如果在生产环境中遇到问题,则无法使用 IDE 远程调试。更糟糕的是,在生产环境中调试是不可接受的,因为它会暂停所有线程,导致服务暂停。

开发人员可以尝试在测试环境或者预发环境中复现生产环境中的问题。但是,某些问题无法在不同的环境中轻松复现,甚至在重新启动后就消失了。

如果您正在考虑在代码中添加一些日志以帮助解决问题,您将必须经历以下阶段:测试、预发,然后生产。这种方法效率低下,更糟糕的是,该问题可能无法解决,因为一旦 JVM 重新启动,它可能无法复现,如上文所述。

Arthas 旨在解决这些问题。开发人员可以在线解决生产问题。无需 JVM 重启,无需代码更改。 Arthas 作为观察者永远不会暂停正在运行的线程。

1.3 Arthas(阿尔萨斯)能为你做什么?

Arthas 是 Alibaba 开源的 Java 诊断工具,深受开发者喜爱。

当你遇到以下类似问题而束手无策时,Arthas可以帮助你解决:

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

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

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

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

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

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

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

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

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

2 window环境搭建

2.1 下载和启动

#下载jar包
curl -O https://arthas.aliyun.com/arthas-boot.jar
# 启动
d:
cd temp
java -jar arthas-boot.jar

2.1 启动后:选择需要监控的服务

输入2:回车 D:\Temp> java -jar arthas-boot.jar [INFO] JAVA_HOME: D:\Java\jdk-17 [INFO] arthas-boot version: 3.6.7 [INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.

  • [1]: 13344 org.jetbrains.jps.cmdline.Launcher [2]: 11652 com.bridge.MybatisMybatisPlusApp

    [3]  14212 

    [4]: 4700 org.jetbrains.idea.maven.server.RemoteMavenServer36 2

3 快速入门

3.1 打开浏览器

http://127.0.0.1:3658/

3.2 开启trace请求

trace -E 类全路径 方法名 -n 5 --skipJDKMethod false '1==1'

  1. 如入需要监控的方法名

    trace -E com.bridge.controler.UserController getUsers -n 5 --skipJDKMethod false '1==1'

    回车后效果

    Affect(class count: 2 , method count: 2) cost in 70 ms, listenerId: 2
    [arthas@11652]$ trace -E com.bridge.controler.UserController getUsers -n 5  --skipJDKMethod false '1==1'
    Press Q or Ctrl+C to abort.

  2. 亲的页面请求后效果如下

    [arthas@11652]$ trace -E com.bridge.controler.UserController getUsers -n 5  --skipJDKMethod false '1==1'
    Press Q or Ctrl+C to abort.
    Affect(class count: 2 , method count: 2) cost in 64 ms, listenerId: 3
    `---ts=2023-04-09 21:37:54;thread_name=http-nio-8080-exec-5;id=58;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@186dcec2
        `---[23.6803ms] com.bridge.controler.UserController$$EnhancerBySpringCGLIB$$ea91532e:getUsers()
            `---[98.58% 23.3448ms ] org.springframework.cglib.proxy.MethodInterceptor:intercept()
                `---[97.18% 22.6864ms ] com.bridge.controler.UserController:getUsers()
                    `---[99.79% 22.6391ms ] com.bridge.service.IUserService:getAll() #38

3.3  查看 dashboard

输入dashboard,按回车/enter,会展示当前进程的信息,按ctrl+c可以中断执行。

$ dashboard
ID     NAME                   GROUP          PRIORI STATE  %CPU    TIME   INTERRU DAEMON
17     pool-2-thread-1        system         5      WAITIN 67      0:0    false   false
27     Timer-for-arthas-dashb system         10     RUNNAB 32      0:0    false   true
11     AsyncAppender-Worker-a system         9      WAITIN 0       0:0    false   true
9      Attach Listener        system         9      RUNNAB 0       0:0    false   true
3      Finalizer              system         8      WAITIN 0       0:0    false   true
2      Reference Handler      system         10     WAITIN 0       0:0    false   true
4      Signal Dispatcher      system         9      RUNNAB 0       0:0    false   true
26     as-command-execute-dae system         10     TIMED_ 0       0:0    false   true
13     job-timeout            system         9      TIMED_ 0       0:0    false   true
1      main                   main           5      TIMED_ 0       0:0    false   false
14     nioEventLoopGroup-2-1  system         10     RUNNAB 0       0:0    false   false
18     nioEventLoopGroup-2-2  system         10     RUNNAB 0       0:0    false   false
23     nioEventLoopGroup-2-3  system         10     RUNNAB 0       0:0    false   false
15     nioEventLoopGroup-3-1  system         10     RUNNAB 0       0:0    false   false
Memory             used   total max    usage GC
heap               32M    155M  1820M  1.77% gc.ps_scavenge.count  4
ps_eden_space      14M    65M   672M   2.21% gc.ps_scavenge.time(m 166
ps_survivor_space  4M     5M    5M           s)
ps_old_gen         12M    85M   1365M  0.91% gc.ps_marksweep.count 0
nonheap            20M    23M   -1           gc.ps_marksweep.time( 0
code_cache         3M     5M    240M   1.32% ms)
Runtime
os.name                Mac OS X
os.version             10.13.4
java.version           1.8.0_162
java.home              /Library/Java/JavaVir
                       tualMachines/jdk1.8.0
                       _162.jdk/Contents/Hom
                       e/jre

3.4 通过 thread 命令来获取到math-game进程的 Main Class

thread 1会打印线程 ID 1 的栈,通常是 main 函数的线程。

$ thread 1 | grep 'main('
    at demo.MathGame.main(MathGame.java:17)

3.5. 通过 jad 来反编译 Main Class

$ jad demo.MathGame
​
ClassLoader:
+-sun.misc.Launcher$AppClassLoader@3d4eac69
  +-sun.misc.Launcher$ExtClassLoader@66350f69
​
Location:
/tmp/math-game.jar
​
/*
 * Decompiled with CFR 0_132.
 */
package demo;
​
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
​
public class MathGame {
    private static Random random = new Random();
    private int illegalArgumentCount = 0;
​
    public static void main(String[] args) throws InterruptedException {
        MathGame game = new MathGame();
        do {
            game.run();
            TimeUnit.SECONDS.sleep(1L);
        } while (true);
    }
​
    public void run() throws InterruptedException {
        try {
            int number = random.nextInt();
            List<Integer> primeFactors = this.primeFactors(number);
            MathGame.print(number, primeFactors);
        }
        catch (Exception e) {
            System.out.println(String.format("illegalArgumentCount:%3d, ", this.illegalArgumentCount) + e.getMessage());
        }
    }
​
    public static void print(int number, List<Integer> primeFactors) {
        StringBuffer sb = new StringBuffer("" + number + "=");
        Iterator<Integer> iterator = primeFactors.iterator();
        while (iterator.hasNext()) {
            int factor = iterator.next();
            sb.append(factor).append('*');
        }
        if (sb.charAt(sb.length() - 1) == '*') {
            sb.deleteCharAt(sb.length() - 1);
        }
        System.out.println(sb);
    }
​
    public List<Integer> primeFactors(int number) {
        if (number < 2) {
            ++this.illegalArgumentCount;
            throw new IllegalArgumentException("number is: " + number + ", need >= 2");
        }
        ArrayList<Integer> result = new ArrayList<Integer>();
        int i = 2;
        while (i <= number) {
            if (number % i == 0) {
                result.add(i);
                number /= i;
                i = 2;
                continue;
            }
            ++i;
        }
        return result;
    }
}
​
Affect(row-cnt:1) cost in 970 ms.

3.6. watch

通过watch命令来查看demo.MathGame#primeFactors函数的返回值:

$ watch demo.MathGame primeFactors returnObj
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 107 ms.
ts=2018-11-28 19:22:30; [cost=1.715367ms] result=null
ts=2018-11-28 19:22:31; [cost=0.185203ms] result=null
ts=2018-11-28 19:22:32; [cost=19.012416ms] result=@ArrayList[
    @Integer[5],
    @Integer[47],
    @Integer[2675531],
]
ts=2018-11-28 19:22:33; [cost=0.311395ms] result=@ArrayList[
    @Integer[2],
    @Integer[5],
    @Integer[317],
    @Integer[503],
    @Integer[887],
]
ts=2018-11-28 19:22:34; [cost=10.136007ms] result=@ArrayList[
    @Integer[2],
    @Integer[2],
    @Integer[3],
    @Integer[3],
    @Integer[31],
    @Integer[717593],
]
ts=2018-11-28 19:22:35; [cost=29.969732ms] result=@ArrayList[
    @Integer[5],
    @Integer[29],
    @Integer[7651739],
]

更多的功能可以查看进阶使用

3.7. 退出 arthas

如果只是退出当前的连接,可以用quit或者exit命令。Attach 到目标进程上的 arthas 还会继续运行,端口会保持开放,下次连接时可以直接连接上。

如果想完全退出 arthas,可以执行stop命令。

4 进阶使用

进阶使用

Web Console在线教程在新窗口打开

4.1 通过浏览器连接 arthas

Arthas 目前支持 Web Console,用户在 attach 成功之后,可以直接访问:http://127.0.0.1:8563/在新窗口打开

可以填入 IP,远程连接其它机器上的 arthas。

img

注意

默认情况下,arthas 只 listen 127.0.0.1,所以如果想从远程连接,则可以使用 --target-ip参数指定 listen 的 IP,更多参考-h的帮助说明。 注意会有安全风险,考虑下面的 tunnel server 的方案。

提示

3.5.4 版本后,在 Web Console 可以鼠标右键复制粘贴。

4.2 scrollback URL 参数

提示

3.5.5 版本后支持

默认 Web Console 支持向上回滚的行数是 1000。可以在 URL 里用scrollback指定。比如

http://127.0.0.1:8563/?scrollback=3000在新窗口打开

4.3 使用 arthas tunnel server

其余参考官网

进阶使用 | arthas

5 idea插件arthas idea

5.1 Arthas-idea(部分命令可视化)

提示

插件由社区开发者提供。

5.2 Alibaba Cloud Toolkit 热部署组件(一键 retransform)

提示

热部署组件支持一键将编辑器中修改的 Java 源码快速编译,并更新到远端应用服务中,免去手动 dump、mc 的过程。此外,也可以一键还原 retransform 的类文件。

img

5.3 安装插件

快速生成命令

对应的方法右击--》选择Arthas Command-->选择对应的命令

在Arthas中输入复制命令【trace -E com.bridge.controller.RedisHashController getSysDictConfig -n 5】图一,接口请求后图二

图一

图二

6 相同功能工具介绍【skywalking】

官方文档

1.1 概念

SkyWalking 是什么?

FROM Apache SkyWalking

分布式系统的应用程序性能监视工具,专为微服务、云原生架构和基于容器(Docker、K8s、Mesos)架构而设计。

提供分布式追踪、服务网格遥测分析、度量聚合和可视化一体化解决方案。

1.2 功能列表

SkyWalking 有哪些功能?

FROM Apache SkyWalking

  • 多种监控手段。可以通过语言探针和 service mesh 获得监控是数据。

  • 多个语言自动探针。包括 Java,.NET Core 和 Node.JS。

  • 轻量高效。无需大数据平台,和大量的服务器资源。

  • 模块化。UI、存储、集群管理都有多种机制可选。

  • 支持告警。

  • 优秀的可视化解决方案。

1.3 整体架构

SkyWalking 整体架构如何?

FROM Apache SkyWalking

架构图

整个架构,分成上、下、左、右四部分:

考虑到让描述更简单,我们舍弃掉 Metric 指标相关,而着重在 Tracing 链路相关功能。

  • 上部分 Agent :负责从应用中,收集链路信息,发送给 SkyWalking OAP 服务器。目前支持 SkyWalking、Zikpin、Jaeger 等提供的 Tracing 数据信息。而我们目前采用的是,SkyWalking Agent 收集 SkyWalking Tracing 数据,传递给服务器。

  • 下部分 SkyWalking OAP :负责接收 Agent 发送的 Tracing 数据信息,然后进行分析(Analysis Core) ,存储到外部存储器( Storage ),最终提供查询( Query )功能。

  • 右部分 Storage :Tracing 数据存储。目前支持 ES、MySQL、Sharding Sphere、TiDB、H2 多种存储器。而我们目前采用的是 ES ,主要考虑是 SkyWalking 开发团队自己的生产环境采用 ES 为主。

  • 左部分 SkyWalking UI :负责提供控台,查看链路等等。

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐