> 文档中心 > Arthas线上问题定位神器

Arthas线上问题定位神器

文章目录

    • 🌞导读
    • 📖Arthas介绍
    • ⏬Arthas如何使用
    • ✅运行
    • ⭐️常用命令
      • 监控面板`dashboard`
      • 线程查看`thread`
      • 获得静态属性值`getstatic`
      • 反编译`jad`
      • 出参入参查看`watch`
      • 检查耗时代码`trace`
      • 方法执行数据的时空隧道`tt`
      • ⭐️万能的`ognl`
      • 更多请[参考](https://arthas.aliyun.com/doc/advanced-use.html#)
    • 🪣Docker如何使用Arthas
    • 问题
    • 🚩吃井不忘挖水人

🌞导读

我在面试时通常都会问求职者的一个问题:你如何定位线上程序cpu飙升,内存占用过高,出现死锁的问题。我发现很多工作了多年的开发者都不知道如何排查线上的问题,甚至没有相关排查经验,出现问题时更快速解决的方案可能是重启,然后在本地尝试复现问题,打断点看

你可能会告诉我,可以远程debug,jdk也为我们提供了jsp、jstat、jmap、jstack、javap一系列工具都可以帮助我们排查问题呀,远程debug会导致线上应用整体阻塞,而jdk自带命令用过的小伙伴肯定会觉得这些命令难以操作,且定位也比较困难。今天我就教大家如何使用Arthas这款神器来快速精准的定位线上问题。

📖Arthas介绍

Arthas是阿里巴巴开源的Java诊断工具,其本身也是一个java程序,可采用命令行与其交互,可方便快速的定位线上运行的问题,深受各大公司开发人员喜爱。

那么它能干什么呢

  • 可视化控制台,直观的观测到程序的运行情况
  • 局部反编译,可具体到方法进行反编译操作
  • 对方法中每一行代码的执行时长进行监控
  • 查看JVM的实时状态
  • 快速定位热点线程以及他占用cpu比例
  • 查看方法的出参入参
  • 直接执行某一段代码
  • 。。。

看到这里,你可能已经跃跃欲试了,接下来让我们试试它到底有多强大吧。

⏬Arthas如何使用

使用方式很简单,我们直接执行以下命令将jar包下载下来即可

# 下载地址一  github下载wget https://alibaba.github.io/arthas/arthas-boot.jar# 下载地址二  gitee下载wget https://arthas.gitee.io/arthas-boot.jar

✅运行

java -jar arthas-boot.jar [pid]# 输入pid编号 选择我们需要监控的程序[INFO] arthas-boot version: 3.5.4[INFO] Process 3492 already using port 3658[INFO] Process 3492 already using port 8563[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.* [1]: 3492 org.jetbrains.idea.maven.server.RemoteMavenServer36  [2]: 5904  [3]: 8280 com.example.demo.DemoApplication

这时候可以看到我们有3个jvm进程,输入相应进程号回车

看到如下信息时,我们就可以使用Arthas命令来进行监控了

[INFO] The target process already listen port 3658, skip attach.[INFO] arthas-client connect 127.0.0.1 3658  ,---.  ,------. ,--------.,--.  ,--.  ,---.   ,---. /  O  \ |  .--. ''--.  .--'|  '--'  | /  O  \ '   .-'|  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |`.  `-.|  | |  ||  |\  \    |  |   |  |  |  ||  | |  |.-'    |`--' `--'`--' '--'   `--'   `--'  `--'`--' `--'`-----'wikihttps://arthas.aliyun.com/doctutorials  https://arthas.aliyun.com/doc/arthas-tutorials.htmlversion    3.5.4main_classpid 8280time2021-10-27 22:29:37

可以看到控制台信息,arthas提供了一个3658的端口号,我们可直接通过浏览器访问http://127.0.0.1:3658,就可以进入到web页面,页面的操作与控制台相同。

Arthas线上问题定位神器

⭐️常用命令

命令 描述
dashboard 当前系统的实时面板
thread 查看当前 JVM 的线程堆栈信息
jvm 查看当前 JVM 的信息
getstatic 查看类的静态属性
ognl 执行ognl命令
heapdump dump java heap, 类似jmap命令的heap dump功能
jad 反编译指定已加载类的源码
monitor 方法执行监控
watch 方法执行数据观测
trace 方法内部调用路径,并输出方法路径上的每个节点上耗时
stack 输出当前方法被调用的调用路径
tt 方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测
quit/stop 退出当前arthas客户端,stop表示关闭服务端,客户端均会退出

我们准备一个类做测试

public class TestDemo {    public static Long age = 30L;    public static Long get() { return age;    }    public static Long add(int i) throws InterruptedException { TimeUnit.SECONDS.sleep(1); System.out.println(get() - 1); return age += i;    }    public static void main(String[] args) throws Exception { for (int i = 0; i < 100000000; i++) {     add(i); } Thread.currentThread().join();    }}

监控面板dashboard

dashboard命令

Arthas线上问题定位神器

该命令监控的是整体信息,包含上(线程信息),中(内存信息),下(基础信息)

线程查看thread

参数名称 参数说明
id 线程id
[n:] 指定最忙的前N个线程并打印堆栈
[b] 找出当前阻塞其他线程的线程
[i ] 指定cpu使用率统计的采样间隔,单位为毫秒,默认值为200
[–all] 显示所有匹配的线程

采样最近5秒最忙的3个线程

thread -n 3 -i 5000

Arthas线上问题定位神器

获得静态属性值getstatic

getstatic com.demo.TestDemo age

结果

field: age@Integer[30]Affect(row-cnt:1) cost in 27 ms.

反编译jad

jad com.demo.TestDemo

Arthas线上问题定位神器

出参入参查看watch

参数名称 参数说明
class-pattern 类名表达式匹配
method-pattern 函数名表达式匹配
express 观察表达式,默认值:{params, target, returnObj}
condition-express 条件表达式
[b] 函数调用之前观察
[e] 函数异常之后观察
[s] 函数返回之后观察
[f] 函数结束之后(正常返回和异常返回)观察
[E] 开启正则表达式匹配,默认为通配符匹配
[x:] 指定输出结果的属性遍历深度,默认为 1
watch com.demo.TestDemo add "{params}" -x 2

Arthas线上问题定位神器

检查耗时代码trace

参数名称 参数说明
class-pattern 类名表达式匹配
method-pattern 方法名表达式匹配
condition-express 条件表达式
[E] 开启正则表达式匹配,默认为通配符匹配
[n:] 命令执行次数
#cost 方法执行耗时
trace com.demo.TestDemo add

Arthas线上问题定位神器

方法执行数据的时空隧道tt

参数名称 参数说明
-t 记录每次执行的情况
-n 限制要记录的次数,防止内存溢出

Arthas线上问题定位神器

⭐️万能的ognl

通过ognl直接调用我们的代码

ognl '@com.demo.TestDemo@get()'

Arthas线上问题定位神器

如果是调用spring bean中的方法只需要调用获取bean的静态方法即可

ognl '@com.demo.SpringContextHolder@getBean("mobileLoginSuccessHandler").defaultAuthorizationServerTokenServices'

更多请参考

🪣Docker如何使用Arthas

如果说你们公司使用的是docker部署的项目,该如何使用Arthas呢?

很简单,我们只需要将Arthas和我们的程序都打入进docker就好了

dockerfile文件如下

FROM openjdk:8-jdk-alpineCOPY --from=hengyunabc/arthas:latest /opt/arthas /opt/arthasMAINTAINER hellohesir@gmail.comENV TZ=Asia/ShanghaiRUN apk add --no-cache tiniRUN mkdir -p /appWORKDIR /app# 将编译好的应用也打入到容器中ADD ./target/app.jar ./app.jarENTRYPOINT ["/sbin/tini", "--", "/bin/sh", "-c", "set -e && java ${JVM_PARAM} -Djava.security.egd=file:/dev/./urandom -jar app.jar && 1"]

问题

如果你使用了如skywalking这一类基于jvm代理实现的软件时,会导致arthas无法正常工作,其原因是arthas是基于JavaAgent代理技术,当arthas尝试转换一个类时,它会触发SkyWalking代理再次增强该类。由于ByteBuddy重新生成了字节码,修改了字段和导入的类名,JVM对类字节码的验证失败,因此重新转换类将不成功。

skywalking的解决方案,新增如下配置中的其中一项,让skywalking先尝试从缓存中加载。

-Dskywalking.agent.class_cache_mode=MEMORY

-Dskywalking.agent.class_cache_mode=FILE

🚩吃井不忘挖水人

arthas官网

感恩开源~