官方地址
离线包安装
如果你的服务是部署在内网或者不能访问互联网的场景,需要安装离线包,不然启动arthas的时候会报错,启动不起来,离线包下载地址:https://arthas.aliyun.com/doc/download.html
启动arthas
下载完成arthas之后,解压对应的arthas 一般我们执行java -jar arthas-boot.jar就能将arthas启动起来了
但是部分环境这个命令是不行的 这个时候可以通过执行sh as.sh来启动arthas 启动完成之后会出现下面这个交互页面 然后通过输入你的目标进程的pid对应的序号 从而进入到对应的arthas
比如我的目标进程是63509这个进程 则需要键入4这个选项,然后回车,就会出现下面这个页面,出现这个页面也就表示进入arthas成功了 ps:目标进程的id 可以通过ps -ef | grep xxx 等方式获取
一些常用的命令
dashboard
作用
查看当前系统的实时数据面板
参数说明
参数名称 | 参数说明 |
---|---|
[i:] | 刷新实时数据的时间间隔 (ms),默认 5000ms |
[n:] | 刷新实时数据的次数 |
当没有参数执行时,执行后页面如下,具体每个数据项表示什么可以参考官方文档
使用参考
如果想要按照一定的时间间隔 执行一定次数 可以按照下面这个命令执行
dashboard -i x -n y
如果x为1000 y为3 那么就会每隔1000毫秒进行刷新一次 运行三次这个命令
logger
这个还有待研究 功能很是强大 后续可以再开发的时候直接输出debug级别的日志 然后产线级别为info 这样不会输出对应的日志 但是我们可以通过调试对应的logger的级别 然后输出对应的日志
memory
作用
查看 JVM 内存信息。可以看到新生代、老年代、代码缓存等的使用情况。
sysprop
作用
查看当前 JVM 的系统属性(System Property)
比如我们在配置文件中配置的属性 可以在这里面进行查看
thread
作用
查看当前线程信息,查看线程的堆栈
参数说明
参数名称 | 参数说明 |
---|---|
id | 线程 id |
[n:] | 指定最忙的前 N 个线程并打印堆栈 |
[b] | 找出当前阻塞其他线程的线程 |
[i ] | 指定 cpu 使用率统计的采样间隔,单位为毫秒,默认值为 200 |
[–all] | 显示所有匹配的线程 |
使用参考
可以通过下面这个命令直接查询当前应用正在工作的线程,默认按照 CPU 增量时间降序排列,只显示第一页数据。
thread
如果想要具体查看某一个线程的堆栈信息 则可以通过thread id的方式查看,id则可以根据上面这个命令获得
比如如果想要看arthas-command-execute这个线程 则可以通过下面这个命令查看
thread 902
如果想要展示所有的匹配的线程则可以通过下面这个命令
thread --all
该命令跟thread的区别就是thread --all 是展示所有的符合的线程,而thread 只会展示第一页的线程。
如果想要列出指定时间内最忙的n个线程 则可以通过下面这个命令
thread -n x -i y
如果是thread -3 x -i 1000 那么就表示列出1000毫秒内 最忙的3个线程
如果想要查看应用应用中线程的阻塞情况则可以通过下面这个命令进行,注意下面这个命令目前只支持找出 synchronized 关键字阻塞住的线程, 如果是java.util.concurrent.Lock, 目前还不支持。
thread -b
通过执行上面这个命令可以看出系统中存在被阻塞的线程,线程阻塞所在的代码在DeadLockController.java:33行,这个时候就可以通过查看源代码,从而定位问题。
jad
作用
反编译指定已加载类的源码
参数说明
参数名称 | 参数说明 |
---|---|
class-pattern | 类名表达式匹配 |
[c:] | 类所属 ClassLoader 的 hashcode |
[classLoaderClass:] | 指定执行表达式的 ClassLoader 的 class name |
[E] | 开启正则表达式匹配,默认为通配符匹配 |
使用参考
以上面的htread -b例子中出现的代码为例,我们如果想要查看com.yedeguo.demo.lock.DeadLockController这个类的源码,我们可以通过执行下面这个命令
jad com.yedeguo.demo.lock.DeadLockController
如果想要只编译类中的某个方法 则可以通过下面这个执行下面这个命令
jad com.yedeguo.demo.lock.DeadLockController dealLock
当有多个 ClassLoader 都加载了这个类时,jad 命令会输出对应 ClassLoader 实例的 hashcode,然后你只需要重新执行 jad 命令,并使用参数 -c 就可以反编译指定 ClassLoader 加载的那个类了;
monitor
作用
方法执行监控
对匹配 class-pattern/method-pattern/condition-express的类、方法的调用进行监控。
monitor 命令是一个非实时返回命令.
实时返回命令是输入之后立即返回,而非实时返回的命令,则是不断的等待目标 Java 进程返回信息,直到用户输入 Ctrl+C 为止。
服务端是以任务的形式在后台跑任务,植入的代码随着任务的中止而不会被执行,所以任务关闭后,不会对原有性能产生太大影响,而且原则上,任何 Arthas 命令不会引起原有业务逻辑的改变。再就是这个命令只有在监控的方法第一次运行之后才会实际进行监控。
监控的维度说明
监控项 | 说明 |
---|---|
timestamp | 时间戳 |
class | Java 类 |
method | 方法(构造方法、普通方法) |
total | 调用次数 |
success | 成功次数 |
fail | 失败次数 |
rt | 平均 RT |
fail-rate | 失败率 |
参数说明
方法拥有一个命名参数 [c:],意思是统计周期(cycle of output),拥有一个整型的参数值
参数名称 | 参数说明 |
---|---|
class-pattern | 类名表达式匹配 |
method-pattern | 方法名表达式匹配 |
condition-express | 条件表达式 |
[E] | 开启正则表达式匹配,默认为通配符匹配 |
[c:] | 统计周期,默认值为 120 秒 |
[b] | 在方法调用之前计算 condition-express |
[m ] | 指定 Class 最大匹配数量,默认值为 50。长格式为[maxMatch ]。 |
使用参考
比如有下面这个方法
package com.yedeguo.demo.arthas;
import java.util.Map;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Description : TODO
* @date : 2023/6/29 17:48
* @author : ydg
*/
@RequestMapping("/api/demo/arthas")
@RestController
public class ArthasController {
@GetMapping("monitor")
public void monitor(@RequestBody Map<String, String> map) {
System.out.println(map);
}
}
如果想要监控这个方法,而不关心参数则可以通过下面这个命令
monitor com.yedeguo.demo.arthas.ArthasController monitor
如果想要监控这个方法输入了指定的参数key以及value都是aa之后的运行情况则可以通过下面这个命令,后面的表达式是ognl表达,可以根据自己的方法情况修改表达式情况。
monitor com.yedeguo.demo.arthas.ArthasController monitor 'params[0].get("aa").equals("aa")'
如果想要想要监控监控x次方法在y秒内的运行情况 则可以通过下面这个命令 下面是监控10次 每次监控范围为10秒
monitor com.yedeguo.demo.arthas.ArthasController monitor -n 10 --cycle 10
trace
作用
查看方法内部调用路径,并输出方法路径上的每个节点上耗时
trace 命令能主动搜索 class-pattern/method-pattern 对应的方法调用路径,渲染和统计整个调用链路上的所有性能开销和追踪调用链路。
参数说明
参数名称 | 参数说明 |
---|---|
class-pattern | 类名表达式匹配 |
method-pattern | 方法名表达式匹配 |
condition-express | 条件表达式 |
[E] | 开启正则表达式匹配,默认为通配符匹配 |
[n:] | 命令执行次数 |
#cost | 方法执行耗时 |
[m ] | 指定 Class 最大匹配数量,默认值为 50。长格式为[maxMatch ]。 |
这里重点要说明的是条件表达式,条件表达式的构成主要由 ognl 表达式组成,所以你可以这样写"params[0]<0",只要是一个合法的 ognl 表达式,都能被正常支持。
使用参考
不带参数直接trace
trace com.yedeguo.demo.arthas.ArthasController monitor
带上监控次数以及不跳过jdk方法
trace com.yedeguo.demo.arthas.ArthasController monitor -n 5 --skipJDKMethod false
带上监控次数、过滤方法中指定参数的值、不跳过jdk方法 输出表达式执行结果
trace com.yedeguo.demo.arthas.ArthasController monitor -n 5 'params[0].get("aa").equals("aa")' --skipJDKMethod false -v
可以看到我跑了两个这个方法,其中一次给出的参数符合表达式,所以输出了这个方法的trace结果,另一次则不符合表达式,所以就没有输出对应的结果。
tt命令
作用
提示
方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测,并且tt命令能够进行请求的回放,也就是能够再次发起请求。
参数说明
参数名称 | 参数说明 |
---|---|
class-pattern | 类名表达式匹配 |
method-pattern | 方法名表达式匹配 |
condition-express | 条件表达式 |
[t] | 这个参数的表明希望记录下类 所有符合上面这些参数的请求的执行情况 |
[n:] | 命令执行次数 |
[m] | 通过 -m 参数指定 Class 匹配的最大数量,防止匹配到的 Class 数量太多导致 JVM 挂起,默认值是 50。 |
使用参考
比如我的服务中有很多个XxController类,时候时候如果想要监控这些类的调用情况,
可以通过下面这个命令
tt -t -n 3 *Controller test
#如果想要精确的查看某个类的方法方法 则可以通过下面这个命令
tt -t com.yedeguo.demo.arthas.TestController test -n 5
可以看到我一共一共有三次请求 其中ArthasController一次、TestController两次,而TestController还有一次异常调用。
如果想要知道那一次异常调用的具体情况,则可以通过下面这个命令,而-i 后面的参数1001 则是通过上面返回的index列拿到的
tt -i 1001
可以看到tt -i命令将异常调用发生的类、所在的方法、入参、异常内容等都展示出来了,通过这个则可以知道异常发生在com.yedeguo.demo.arthas.TestController.test(TestController.java:27)这行代码,从而可以进一步定位问题。
而如果想要重做一次调用也是可以的,可以通过下面这个命令执行
tt -i 1001 -p
watch
作用
让你能方便的观察到指定函数的调用情况。能观察到的范围为:返回值、抛出异常、入参,通过编写 OGNL 表达式进行对应变量的查看。
参数说明
watch 的参数比较多,主要是因为它能在 4 个不同的场景观察对象
参数名称 | 参数说明 |
---|---|
class-pattern | 类名表达式匹配 |
method-pattern | 函数名表达式匹配 |
express | 观察表达式,默认值:{params, target, returnObj} |
condition-express | 条件表达式 |
[b] | 在函数调用之前观察 |
[e] | 在函数异常之后观察 |
[s] | 在函数返回之后观察 |
[f] | 在函数结束之后(正常返回和异常返回)观察 |
[E] | 开启正则表达式匹配,默认为通配符匹配 |
[x:] | 指定输出结果的属性遍历深度,默认为 1,最大值是 4 |
[m ] | 指定 Class 最大匹配数量,默认值为 50。长格式为[maxMatch ]。 |
使用参考
最简单的一个用法就是如下 下面这个写法就是监控了ArthasController类的monitor方法 监控请求5次 属性遍历深度3级
watch com.yedeguo.demo.arthas.ArthasController monitor '{params,returnObj,throwExp}' -n 5 -x 3
效果如下 我请求了两次 第一次是正常访问 可以看到入参、返回返回结果都是有值的 而异常是没有值的
而第一次是异常访问 可以看到入参、异常是有值的 而返回结果是没有值的
而如果针对入参进行一些过滤的话 则可以通过ognl进行相应的过滤 比如下面这个命令
就是对第一个入参(我的这个参数类似是Map)中的as属性进行过滤 需要aa的值等于bb才会被watch
否则不会被watch
watch com.yedeguo.demo.arthas.ArthasController monitor '{params,returnObj,throwExp}' "params[0].get('aa').equals('bb')" -n 5 -x 3
如果是一个重载方法的话 方法定义如下
public interface ArthasService {
void monitor();
void monitor(Map<String,String> map);
void monitor(String param);
}
如果我想要监控第二个方法的话 则可以通过下面这个命令
注意:我在命令后面加上了-v 表示将表达式的执行结果也进行了打印
watch com.yedeguo.demo.arthas.ArthasService monitor '{params,returnObj,throwExp}' "params.length==1 && params[0] instanceof java.util.Map" -n 5 -x 3 -v
效果如下 可以看到一共有三个Condition express 其中两个为false 也就是第一个跟、第三个方法匹配这个表达式失败 然后第二个方法匹配表达式成功所以被监控展示出来了相关的内容
而如果想要观察一个方法执行前后方法的入参、出参的变化,比如你入参是一个map,然后在方法执行过程中将map中的某些值进行了更新 这个时候如果想要查看执行前后的变化,可以通过下面这个命令
watch com.yedeguo.demo.arthas.ArthasService monitor '{params,returnObj,throwExp}' "params.length==1 && params[0] instanceof java.util.Map" -n 5 -x 3 -v -b -s
效果如下:可以看到Condition express出现了6次 这个因为另外两个重载方法不符合 所以为false 而第二个人方法符合了 所以会前后两次被打印出来 而我在这个方法里面讲map中的aa属性的值进行了更新 更新成了cc 所以可以再下面看出来 方法执行前aa的值是bb 方法执行后 aa的值变成了cc
如果想要指定一个方法执行前后 当前对象的属性 则可以通过下面这个命令
watch com.yedeguo.demo.arthas.ArthasController monitor 'target' -n 5 -x 3
效果如下:可以看到this中的param的属性为cc
arthas idea插件
如果想要方便的获取一些arthas命令 可以下载这个插件
安装完成之后效果如下 可以通过在指定的方法上面右键 然后就会出现对应的Arthas Command命令
里面有一些常用的arthas命令
比如选中watch之后就会得到下面这个命令 可以看到这个命令就是对我选中的这个方法的入参、返回值、异常进行了监控 执行5次 参数深度为3 而你可以再这个命令的基础之后 额外加上你的需求 从而得到一个你想要的命令
这样相对的可以有一些简化
watch com.yedeguo.demo.arthas.ArthasServiceImpl monitor '{params,returnObj,throwExp}' -n 5 -x 3