阿里开源诊断工具-Arthas的使用。

参考:
https://segmentfault.com/a/1190000019413202
https://alibaba.github.io/arthas/install-detail.html

下载

  1. curl -sk https://arthas.gitee.io/arthas-boot.jar -o ~/.arthas-boot.jar && echo "alias as.sh='java -jar ~/.arthas-boot.jar --repo-mirror aliyun --use-http'" >> ~/.bashrc && source ~/.bashrc

方式一:

  1. # 安装
  2. curl -O https://arthas.gitee.io/arthas-boot.jar
  3. # 启动arthas,会进入命令行交互状态
  4. java -jar arthas-boot.jar
  5. # 退出
  6. quit
  7. # 也可以指定IP
  8. java -jar arthas-boot.jar --target-ip 0.0.0.0

方式二:

  1. # 安装
  2. curl -L https://alibaba.github.io/arthas/install.sh | sh
  3. # 启动arthas,会进入命令行交互状态
  4. ./as.sh
  5. # 查看arthas命令手册
  6. ./as.sh -h

基础使用

选择要诊断的程序,进入命令行:

image.png

dashbord

通过dashboard命令可以实时查看应用监控数据

image.png

线程


输入thread命令,会显示所有线程的状态信息
输入thread -b 会显示当前处于BLOCKED状态的线程,可以排查线程锁的问题

image.png

查看具体线程:thread id

输入thread -n 3会显示当前最忙的3个线程,可以用来排查线程CPU消耗

image.png

JVM

输入jvm命令,查看jvm详细的性能数据

image.png

监视函数参数和返回值

  1. watch com.alvin.controller.PageController getPage "{params,returnObj}" -x 2

image.png

监视函数调用时间

trace可以监视每一行代码执行的时间

  1. trace com.alvin.controller.PageController getPage

image.png

idea插件

arthas idea https://plugins.jetbrains.com/plugin/13581-arthas-idea

自动生成代码监视语句。

语雀说明文档

github

常用功能

配置静态applicationContext

可以获取spring变量、调用spring方法。

1、放置application类。

ApplicationContextProvider.java

2、配置
image.png
3、复制命令,并执行

image.png

反编译

image.png
效果
image.png

获取spring对象

我们可以直接获取spring对象的属性,还能手动调用里面的方法。

源码

image.png

获取类加载器
image.png

静态属性

  1. ognl -x 3 '@com.alvin.arthas.ArthasUtil@a' -c 20ad9418

image.png

静态方法

  1. ognl -x 3 '@com.alvin.arthas.ArthasUtil@test("1")' -c 20ad9418

image.png

普通属性

  1. ognl -x 3 '#springContext=@com.alvin.arthas.ApplicationContextProvider@context,#springContext.getBean("arthasUtil").b' -c 20ad9418

image.png

普通方法

  1. ognl -x 3 '#springContext=@com.alvin.arthas.ApplicationContextProvider@context,#springContext.getBean("arthasUtil").test2("2")' -c 20ad9418

image.png

获取spring环境变量

image.pngx

  1. ognl -x 3 '#springContext=@com.alvin.common.ApplicationContextProvider@context,#springContext.getEnvironment().getProperty("server.port")' -c 439f5b3d

统计函数执行效率

monitor

  1. # 每十秒统计一次
  2. monitor com.alvin.controller.LightEventPublisher publish -c 10

image.png

监视方法的入参和出参

watch

监视方法的内部行执行时间

trace

其他

tt 函数隧道

记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测

通过tt也可以获取spring容器。

  1. 获取上次执行类,-n 统计次数
  2. tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod -n 1
  3. 通过target获取spring容器
  4. tt -i 1000 -w 'target.getApplicationContext().getBean("arthasUtil").b' -c 20ad9418

image.png

查看有什么类

search class
image.png

查看有什么方法

search method
image.png

获取代理类(controller service)

1、工具类

  1. package com.alvin.util;
  2. import org.springframework.aop.framework.AdvisedSupport;
  3. import org.springframework.aop.framework.AopProxy;
  4. import org.springframework.aop.support.AopUtils;
  5. import java.lang.reflect.Field;
  6. public class AopTargetUtils {
  7. /**
  8. * 获取 目标对象
  9. * @param proxy 代理对象
  10. * @return
  11. * @throws Exception
  12. */
  13. public static Object getTarget(Object proxy) throws Exception {
  14. if(!AopUtils.isAopProxy(proxy)) {
  15. return proxy; //不是代理对象
  16. }
  17. if(AopUtils.isJdkDynamicProxy(proxy)) {
  18. return getJdkDynamicProxyTargetObject(proxy);
  19. } else { //cglib
  20. return getCglibProxyTargetObject(proxy);
  21. }
  22. }
  23. private static Object getCglibProxyTargetObject(Object proxy) throws Exception {
  24. Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0");
  25. h.setAccessible(true);
  26. Object dynamicAdvisedInterceptor = h.get(proxy);
  27. Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised");
  28. advised.setAccessible(true);
  29. Object target = ((AdvisedSupport)advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget();
  30. return target;
  31. }
  32. private static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception {
  33. Field h = proxy.getClass().getSuperclass().getDeclaredField("h");
  34. h.setAccessible(true);
  35. AopProxy aopProxy = (AopProxy) h.get(proxy);
  36. Field advised = aopProxy.getClass().getDeclaredField("advised");
  37. advised.setAccessible(true);
  38. Object target = ((AdvisedSupport)advised.get(aopProxy)).getTargetSource().getTarget();
  39. return target;
  40. }
  41. }

2、命令

  1. ognl -x 3 '#springContext=@com.alvin.arthas.ApplicationContextProvider@context,#proxyBean=#springContext.getBean("lightEventPublisher"),@com.alvin.util.AopTargetUtils@getTarget(#proxyBean).a' -c 20ad9418

查看线程死锁

代码

image.png

查看死锁:

image.png