arthas快速入门

297 阅读3分钟

arthas

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

启动 math-game

curl -O https://arthas.aliyun.com/math-game.jar
java -jar math-game.jar

math-game是一个简单的程序,每隔一秒生成一个随机数,再执行质因数分解,并打印出分解结果。

运行结果

image.png

启动 arthas

curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar

运行结果

image.png 然后这里要我们选择需要监控的jar包,我们目前只有一个,我们输入1

image.png

如果所示,就是启动安装好了,然后我们就进入了他的命令行

查看当前服务运行的参数 JVM、内存、启动参数等

memory

查看当前堆和非堆的内存使用情况

image.png

如图所示,这是我们的内存占用情况,下图就是对里面各个字段的解释

image.png

thread

一般主要用于系统卡死可以用来查看被哪个线程全部占用

# 查看全部的线程状态
thread

# 查看当前最忙的 n个线程
thread -n

# 查看被阻塞的线程
thread -b

执行的结果

image.png

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

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

image.png

查看源码

通过 jad 来反编译 Main Class

 jad demo.MathGame

执行结果

image.png

查看当前类的方法

sm demo.MathGame

执行结果

image.png

如图所示

image.png

修改线上源码

修改的原理就是 把 新的class 加载到JVM 里面去,生成 class的方式有2种

  1. 把你本地的 class上传到服务器
  2. 通过 arthas的 jad命令来把 class反编译成 java ,mc 命令来把 java 编译成 class
  3. retransform 命令把 class加载到 jvm中去
#1、从原class 里面复制出新的 java文件(有可能反编译会有问题,建议先检查下结果)
jad --source-only demo.MathGame > /MathGame.java
    
#2、修改java里面的内容为你想要的内容


# 3、使用 mc 把你的java 编译成 class
mc /MathGame.java -d /

# 4、把新的class 加载到JVM中去
retransform /demo/MathGame.class

第一条命令执行的结果,将class里面的文件复制到/MathGame.java这里

image.png

复制结果如下

image.png

然后我们修改内容为我们想要的内容,修改结果如下,加上了一个打印结果

image.png

使用 mc 把你的java 编译成 class,可以看到输出路径

image.png

可以看到文件

image.png

把新的class 加载到JVM中去,结果如图所示

image.png 可以看到打印了

image.png

监控线上代码

  1. monitor 间隔N秒,统计 某个方法 成功次数、失败次数、平均耗时、失败率
  2. stack 打印整个栈的信息,太长了感觉没啥用
  3. trace 监控某个方法各个步骤的耗时

monitor

# 每隔 5s 监控一下MathGamer 类的 print 方法

monitor -c 5 demo.MathGame print

运行结果,如图所示

image.png

trace (排查慢接口好帮手)

# 监控一下MathGamer 类的 print 方法的执行耗时
trace demo.MathGame print

运行结果如图所示,最前面的0.26ms表示这个接口的耗时

image.png

如果出现某个接口耗时很久,则会出现爆红,下面是网图,可以看到耗时很久的接口就会爆红

image.png

参数过滤

  1. github.com/alibaba/art…
  2. github.com/alibaba/art…

监控某个参数的值

@GetMapping("/test1")
public void test1(@RequestParam String str, @RequestParam Integer age)  {
    System.out.println(str + "  " + age);
}

# 监控 str == zxc
trace cn.data.process.api.web.WkDataController test1 "params[0] == 'zxc'"

# 监控 age >= 1
trace cn.data.process.api.web.WkDataController test1 "params[1] >= 1"