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  \ '   .-'
|  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |`.  `-.
|  | |  ||  |\  \    |  |   |  |  |  ||  | |  |.-'    |
`--' `--'`--' '--'   `--'   `--'  `--'`--' `--'`-----'


wiki       https://arthas.aliyun.com/doc
tutorials  https://arthas.aliyun.com/doc/arthas-tutorials.html
version    3.5.4
main_class
pid        8280
time       2021-10-27 22:29:37

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

image-20211027225821627

⭐️常用命令

命令描述
dashboard当前系统的实时面板
thread查看当前 JVM 的线程堆栈信息
jvm查看当前 JVM 的信息
getstatic查看类的静态属性
ognl执行ognl命令
heapdumpdump 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命令

image-20220418192752836

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

线程查看thread

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

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

thread -n 3 -i 5000

image-20220418192859161

获得静态属性值getstatic

getstatic com.demo.TestDemo age

结果

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

反编译jad

jad com.demo.TestDemo

image-20220418193054966

出参入参查看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

image-20220418193436692

检查耗时代码trace

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

image-20220418193810546

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

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

image-20220418194002645

⭐️万能的ognl

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

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

image-20220418194834949

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

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

更多请参考

🪣Docker如何使用Arthas

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

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

dockerfile文件如下

FROM openjdk:8-jdk-alpine
COPY --from=hengyunabc/arthas:latest /opt/arthas /opt/arthas
MAINTAINER hellohesir@gmail.com
ENV TZ=Asia/Shanghai
RUN apk add --no-cache tini
RUN mkdir -p /app

WORKDIR /app
# 将编译好的应用也打入到容器中
ADD ./target/app.jar ./app.jar

ENTRYPOINT ["/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官网

感恩开源~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值