写点什么

Arthas 阿里开源的 Java 诊断工具

作者:Ayue、
  • 2021 年 12 月 04 日
  • 本文字数:3051 字

    阅读完需:约 10 分钟

Arthas阿里开源的Java诊断工具

Arthas 能做什么

当我们的项目上线后可能遇到以下问题:


  1. 这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?

  2. 我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?

  3. 遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?

  4. 线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!

  5. 是否有一个全局视角来查看系统的运行状况?

  6. 有什么办法可以监控到 JVM 的实时运行状态?

  7. 怎么快速定位应用的热点,生成火焰图?

  8. 怎样直接从 JVM 内查找某个类的实例?


一般通过 JDK 自带的诊断工具去排查问题,不仅不好看而且需要记得很多的命令,而Arthas支持 JDK 6+,支持 Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。


官方文档:https://arthas.aliyun.com/doc/

准备

Arthas 其实就是一个 jar 包,不需要安装,在GitHub可以下载,同时我也准备了Arthas 3.5.4版本(提取码:udhi)。


官方推荐使用arthas-boot,我们下载之后解压,如下:


启动

通过以下命令启动:


java -jar arthas-boot.jar
复制代码



启动之后需要我们选择应用 Java 进程,我们这里选择 1 ,就成功启动了:


常用命令

在官方文档的进阶使用介绍了 Arthas 的命令,我们也可以使用 help 查看帮助(全英文,我看不懂)。



因为是全英文,如果英语不好的人只能望而却步了,但是看官方文档也是十分的方便。

dashboard

当前系统的实时数据面板。


注意在 arthas 中,有 tab 键填充功能,如果你只记得命令的开头几个字母,你可以 tab 补齐,所以比较好用。但是这个界面是实时刷新的,一般 5s 刷新一次,使用 q 键退出刷新(没有退出 arthas,如果要退出,使用ctrl+c )。


thread

这个命令和 jstack 很相似,但是功能更加强大,主要是查看当前 JVM 的线程堆栈信息。



thread -i 1000 -n 3


每过 1000 毫秒进行采样,显示最占 CPU 时间的前 3 个线程。



thread –b


找出阻塞当前线程的线程。


如下面一段代码:


/** * 类说明:演示死锁的产生,2个线程分别持有自己的锁,在不释放的情况下又想去获取对方的锁 */public class NormalDeadLock {
private static Object lock1 = new Object();//第一个锁 private static Object lock2 = new Object();//第二个锁
//第一个拿锁的方法 private static void lock1Do() throws InterruptedException { String threadName = Thread.currentThread().getName(); synchronized (lock1) { System.out.println(threadName + " get lock1"); Thread.sleep(100); synchronized (lock2) { System.out.println(threadName + " get lock2"); } } }
//第二个拿锁的方法 private static void lock2Do() throws InterruptedException { String threadName = Thread.currentThread().getName(); synchronized (lock2) { System.out.println(threadName + " get lock2"); Thread.sleep(100); synchronized (lock1) { System.out.println(threadName + " get lock1"); } } }
//子线程代表lock2 private static class Lock2 extends Thread { private String name;
public Lock2(String name) { this.name = name; }
@Override public void run() { Thread.currentThread().setName(name); try { lock1Do(); } catch (Exception e) { e.printStackTrace(); } } }
public static void main(String[] args) throws InterruptedException { //主线程代表lock1 Thread.currentThread().setName("lock1"); Lock2 lock2 = new Lock2("lock2"); lock2.start(); lock2Do(); }}
复制代码



如果有死锁,会有红色的字提醒着,这个阻塞的线程已经被另外一个线程,如下:



thread --state WAITING


查看处于等待状态的线程。


jvm

查看当前 JVM 信息。


jad

反编译指定已加载类的,可以查看代码是否提交更新或者在排错的时候查看别人写的代码。


命令:jad 指定的类,可用tab补齐。


trace

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


比如使用一个 SpringBoot 项目,控制层 getOrder 方法调用了 orderService.getOrder(orderId),这个方法中分别进行 check、service、redis、mysql 等操作。就可以根据这个命令跟踪出来哪里的耗时最长。因此trace 能方便的帮助你定位和发现因 RT(Response Time,响应时间。一般系统 RT 100ms 以内是比较正常的,300ms 勉强可以接受,1s 以上的话自己看着办吧。) 高而导致的性能问题缺陷,但其每次只能跟踪一级方法的调用链路。


栗子:


@RestController@RequestMapping("/trace")public class TraceController {
@RequestMapping("/getOrder") public String getOrder(@RequestParam("orderId") String order) { StringBuffer buffer = new StringBuffer(); //模拟check操作 String check = check(order); String service = service(order); String redis = redis(order); String mysql = mysql(order); buffer.append(check).append(service).append(redis).append(mysql); return buffer.toString(); }
//检查订单编号是否正确 public String check(String order) { try { Thread.sleep(50); return "订单编号check正常</br>"; } catch (InterruptedException e) { e.printStackTrace(); } return "fail"; }
//模拟业务操作 public String service(String order) { try { Thread.sleep(60); return "通过订单编号业务操作service正常</br>"; } catch (InterruptedException e) { e.printStackTrace(); } return "fail"; }
//模拟redis查询 public String redis(String order) { try { Thread.sleep(30); return "通过订单编号查询redis正常</br>"; } catch (InterruptedException e) { e.printStackTrace(); } return "fail"; }
//模拟mysql查询 public String mysql(String order) { try { Thread.sleep(30); return "通过订单编号查询mysql正常</br>"; } catch (InterruptedException e) { e.printStackTrace(); } return "fail"; }}
复制代码


访问:http://localhost:8080/trace/getOrder?orderId=2



通过trace命令查看:


monitor

方法执行监控。如每 5 秒统计一次某个类的某个方法的方法执行情况。


watch

观察方法的入参出参信息。如:返回值、抛出异常、入参。


还是上面的代码,我们查看方法的入参和返回值可以这样:


watch cn.javatv.demo.controller.TraceController getOrder '{params[0],returnObj}'
复制代码


总结

Arthas 是一个很优秀的 java 诊断工具,无论是安装还是使用都很简洁,这里只是列出了部分,如果你需要学习使用,建议查看官方文档和手动尝试。


Arthas 命令列表:



参考:arthas使用介绍

发布于: 4 小时前阅读数: 8
用户头像

Ayue、

关注

还未添加个人签名 2019.10.16 加入

学习知识,目光坚毅

评论

发布
暂无评论
Arthas阿里开源的Java诊断工具