侧边栏壁纸
  • 累计撰写 1,958 篇文章
  • 累计创建 73 个标签
  • 累计收到 20 条评论

目 录CONTENT

文章目录

Arthas

猿哥
2022-04-07 / 0 评论 / 0 点赞 / 294 阅读 / 0 字

一、介绍

Arthas是阿里的一款开源Java诊断工具。

官方地址:https://arthas.aliyun.com/doc/

下载地址:https://arthas.aliyun.com/doc/download.html

二、安装启动

安装

windwos:

通过下载页面从mave仓或者github链接进行下载。

linux:

wget https://arthas.gitee.io/arthas-boot.jar

启动命令

Arthas 只是一个 java 程序,所以可以直接用 java -jar 运行。

#windows
 java -jar arthas-boot.jar
#linux
 java -jar arthas-boot.jar 或者 ./as.sh
注:机器上有java进程才能启动成功
打印帮助信息:

java -jar arthas-boot.jar -h

选择进程序列号

启动成功后根据获取到的java进程,选择要监测的 Java 进程的序列号【1】、【2】等。

image

在出现 Arthas Logo 之后就可以使用命令进行问题诊断了。

image

webconsole

成功启动连接进程之后就已经自动启动,可以直接访问 http://127.0.0.1:8563/ 访问,页面上的操作模式和控制台完全一样。

image

退出

使用 shutdown 退出时 Arthas 同时自动重置所有增强过的类 。

其他启动方式

# 运行方式1,先运行,再选择 Java 进程 PID
java -jar arthas-boot.jar
# 选择进程(输入[]内编号(不是PID)回车)
[INFO] arthas-boot version: 3.1.4
[INFO] Found existing java process, please choose one and hit RETURN.
* [1]: 11616 com.Arthas
  [2]: 8676
  [3]: 16200 org.jetbrains.jps.cmdline.Launcher
  [4]: 21032 org.jetbrains.idea.maven.server.RemoteMavenServer
# 运行方式2,运行时选择 Java 进程 PID
java -jar arthas-boot.jar [PID]
查看java进程:

linux可以用ps命令查看

windows用jps命令查看,如下:

# 查看运行的 java 进程信息
$ jps -mlvV 
# 筛选 java 进程信息
$ jps -mlvV | grep [xxx]
其他的启动方式请参考:https://arthas.aliyun.com/doc/download.html

三、常用命令

常用命令

下面列举一些 Arthas 的常用命令,看到这里你可能还不知道怎么使用,别急,后面会一一介绍。

命令 介绍 其他
dashboard 当前系统的实时数据面板
thread 查看当前 JVM 的线程堆栈信息
watch 方法执行数据观测
trace 方法内部调用路径,并输出方法路径上的每个节点上耗时
stack 输出当前方法被调用的调用路径
tt 方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测
monitor 方法执行监控
jvm 查看当前 JVM 信息
vmoption 查看,更新 JVM 诊断相关的参数
sc 查看 JVM 已加载的类信息 #查看某个类的字段
sc -d -f com.Arthas
sm 查看已加载类的方法信息 #查看某个类的方法
sm com.Arthas
jad 反编译指定已加载类的源码 # 反编译只显示源码
jad --source-only com.Arthas
# 反编译某个类的某个方法
jad --source-only com.Arthas mysql
ognl 查看变量中的值 #查看静态变量 hashSet 信息
ognl '@com.Arthas@hashSet'
#查看静态变量 hashSet 大小
ognl '@com.Arthas@hashSet.size()'
#对变量中的值进行操作
ognl '@com.Arthas@hashSet.add("test")'
ognl '@com.Arthas@hashSet'
classloader 查看 classloader 的继承树,urls,类加载信息
heapdump 类似 jmap 命令的 heap dump 功能

全局监控

arthas启动后,输入dashboard,可以概览程序的 线程、内存、GC、运行环境信息。

image

四、常见线上问题排查

CPU使用率过高排查

通过dashboard概览可以看到有一个线程的CPU使用率非常高。

dashboard是动态的不方便定位,可以输入命令 *thread *查看所有线程信息。

image

输入命令:thread 14,查看具体的线程内容,14是thread面板中高耗CPU线程的id。

image

输入命令:** jad devtao.Arthas** ,反编译有问题的java类进行查看,jad命令后加thread中判断有问题的java类

image

找到代码的第66行,发现是一个while true的循环,至此找到问题根源。

image

线程问题排查

线程池状态

定位线程问题之前,先回顾一下线程的几种常见状态:

  • RUNNABLE 运行中
  • TIMED_WAITING 调用了以下方法的线程会进入TIMED_WAITING
  • Thread#sleep()
  • Object#wait() 并加了超时参数
  • Thread#join() 并加了超时参数
  • LockSupport#parkNanos()
  • LockSupport#parkUntil()
  • WAITING 当线程调用以下方法时会进入WAITING状态:
  • Object#wait() 而且不加超时参数
  • Thread#join() 而且不加超时参数
  • LockSupport#park()
  • BLOCKED 阻塞,等待锁

Waitting线程处理

thread

thread **当线程太多的时候,可以用grep命令,thread |grep xxx**,xxx是线程名称的关键字(区分大小写),过滤显示关键线程。

image

thread 序号

找到需要排查的线程,thread 17,17是线程在arths中的序号,可以看到有TIMED_WAITTING的线程,Arthas的47行代码sleep了。

image

jad 类名

查看代码定位问题jad devtao.Arthas,jad命令后devtao.Arthas是类名

image

可以看到47行Thread.Sleep()方法触发TIME_WAITING状态了。

死锁(Blocked)线程处理

thread -b

判断死锁线程除了用thread命令查看线程的状态外,还可以直接使用 thread -b 命令查看直接定位到死锁信息。

image

jad 类名

看到死锁出现在Arthas.java 128行,反编译:jad devtao.Arthas

image

128行,可以看到Thread.currentThread()引起的死锁,因为代码里的线城池是1,两个线程抢占资源所以引起死锁。

线上问题需要具体的根据代码上下文进行排查。

程序运行问题排查

追踪方法耗时

使用 trace 命令可以跟踪统计方法耗时。

如下代码统计/user接口的耗时,即统计devtao.controller.UserController#getUser的耗时,代码如下:

image

执行命令:*trace devtao.controller.UserController getUser , *格式:trace 类名 方法名

image

执行trace命令之后,可以看到该方法每次被调用所花费的时间。如该例,可以看到是devtao.service.impl.UserServiceImpl#get方法耗时比较多,再追踪此方法的耗时,

执行命令:trace devtao.service.impl.UserServiceImpl get

image

可以看到service的get方法中每个调用的用时,check方法0.0133ms,servcie 0.0834ms,redis 0.2152ms,mysql 5.5872ms。

统计方法耗时

每5秒统计一下UserServiceImpl的get方法耗时,

** monitor -c 5 devtao.service.impl.UserServiceImpl get**

image

可以看到每5秒内该方法一共被调用多了多少次,平均耗时。

查看方法信息

使用 watch 命令轻松查看输入输出参数以及异常等信息。输入wathc -h查看使用帮助:

[arthas@101192]$ watch -h
 USAGE:
   watch [-b] [-e] [--exclude-class-pattern <value>] [-x <value>] [-f] [-h] [-n <value>] [--listenerId <value>] [-E] [-M <value>] [-s] [-v] class-pattern method-pattern [express] [condition-express]

 SUMMARY:
   Display the input/output parameter, return object, and thrown exception of specified method invocation
   The express may be one of the following expression (evaluated dynamically):
           target : the object
            clazz : the object's class
           method : the constructor or method
           params : the parameters array of method
     params[0..n] : the element of parameters array
        returnObj : the returned object of method
         throwExp : the throw exception of method
         isReturn : the method ended by return
          isThrow : the method ended by throwing exception
            #cost : the execution time in ms of method invocation
 Examples:
   watch org.apache.commons.lang.StringUtils isBlank
   watch org.apache.commons.lang.StringUtils isBlank '{params, target, returnObj, throwExp}' -x 2
   watch *StringUtils isBlank params[0] params[0].length==1
   watch *StringUtils isBlank params '#cost>100'
   watch -f *StringUtils isBlank params
   watch *StringUtils isBlank params[0]
   watch -E -b org\.apache\.commons\.lang\.StringUtils isBlank params[0]
   watch javax.servlet.Filter * --exclude-class-pattern com.demo.TestFilter
常用的watch举例:

# 查看入参和出参
$ watch com.Arthas addHashSet '{params[0],returnObj}'
# 查看入参和出参大小
$ watch com.Arthas addHashSet '{params[0],returnObj.size}'
# 查看入参和出参中是否包含 'count10'
$ watch com.Arthas addHashSet '{params[0],returnObj.contains("count10")}'
# 查看入参和出参,出参 toString
$ watch com.Arthas addHashSet '{params[0],returnObj.toString()}'

查看方法的调用路径

使用 stack命令查看方法的调用信息。

# 观察类devtao.service.imp.UserServiceImpl的 mysql 方法调用路径

stack devtao.service.impl.UserServiceImpl mysql

image

记录方法执行的详细情况

tt -t devtao.service.impl.UserServiceImpl get ,格式为:tt -t 类名 方法名

image

可以看到记录中 INDEX=1000、1001、1002 的记录的 IS-EXP = true ,说明调用出现异常。

查看记录的方法调用信息:tt -l

image

查看调用记录的详细信息(-i 指定 INDEX):tt -i 1001

image

可以看到 INDEX=1001 的记录的异常信息。

重新发起调用,使用指定记录,使用 -p 重新调用:tt -i 1001 -p

image

0
博主关闭了所有页面的评论