⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 juejin.cn/post/7021725088659701791 「wingli」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注**微信公众号:【芋道源码】**有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言将得到认真回复。甚至不知道如何读源码也可以请教噢
  4. 新的源码解析文章实时收到通知。每周更新一篇左右
  5. 认真的源码交流微信群。

一、初识Arthas

说起来,第一次接触Arthas不是因为我正需要用到它(因为我压根就不知道能有这种能力的工具),而是朋友的推荐,当我了解它拥有的能力之后,我震惊了,世上竟有如此powerful的东西。如果你是初次接触Arthas,那么恭喜你,你发现了宝藏。

1.使用前:日志满天下

以前,我们排查问题最常用的方法就是日志:

  • 这个方法报错了,参数传了啥?打日志
  • 这个if为啥没进去?打两条日志
  • 这个方法执行了多少次?循环打日志
  • 请求耗时很慢,那个环节比较慢?花式打日志 当线上出现问题的时候,也是通过日志来定位,比较尴尬的是,日志加上去,发版,服务就需要重启,这样会导致一些问题:
  • 一是对服务有影响,该时刻请求会被中断,进而失败(当时没有摘流量这种操作)
  • 二是重启后问题现场已经被破坏了,无法复现问题
  • 三是日志过多,落盘会导致io升高,磁盘容量需求也变高,日志查询速度也变慢
  • 四是加一次日志往往还不能定位到问题,需要加几次

实践中发现,遇到的许多问题,如果能打日志时能遵循日志规范,是能够轻松定位的,但往往在团队开发中,从日志规范->规范日志,是一个艰巨的,持续性的任务.

2.使用后:一个能打的都没有

可以不太恰当地说,熟练使用Arthas就像在线上开了Debug一样,甚至在某些方面比Debug更加便捷和强大。

  • 想看方法的调用信息?Easy
  • 依赖包混乱,不知道实际运行用了哪个?So Easy
  • 怀疑线程在摸鱼?Very Easy
  • 热更新代码?比较麻烦,但可以

当你线上遇到问题无从下手时,也可以做一下类比:这个问题,如果你能打断点,那你会怎么操作?这个操作能否用Arthas命令实现?

二、kotlin/jvm 也能用

随着kotlin的使用越来越广泛,Arthas能否用于kotlin也是一个值得思考的问题。kotlin编译之后跟java一样也是class文件,而Arthas是运行于jvm中的,主要功能也是通过对增强字节码来实现的,因此源码是kotlin的小伙伴也是适用的,美中不足的是,涉及到字节码反编译的时候,会跟kotlin的源码差异较大,会看到一些以kotlin开头的包名和方法(kotlin的语法糖实现类),不像java的那么直白。

三、必备知识

https://arthas.aliyun.com/doc/quick-start.html 有很详尽的说明,此处仅是简单说明

1.启动Arthas

//首先下载 arthas-boot.jar 启动程序,下边是通过curl来下载,也可以浏览器直接访问该链接下载
curl -O https://arthas.aliyun.com/arthas-boot.jar
//直接执行该启动jar包即可,启动后会提示选择需要“Debug”的jvm进程,
java -jar arthas-boot.jar
//也可以直接通过 ps -ef 等命令找到jvm进程的pid(如下方的 3425),然后添加到末尾,这样可以直接关联jvm进程,不需要选择
java -jar arthas-boot.jar 3425

2.启动过程示意

简单示意,想详细了解的小伙伴可以看Arthas的https://github.com/alibaba/arthas

启动过程示意

  • 通过jvm的机制,可以使正在运行的应用去加载指定的代码,并且拥有更改字节码的能力
  • Arthas是区分client和server的,client独立运行,server依附在宿主应用上

由此也可以衍生出一个使用Arthas的思路,假设你能够让正在运行的应用执行指定代码,或者添加代码到已有逻辑里边,那你会怎么利用这个特性解决你遇到的问题

3.探针Javaagent

如果说对javaagent有印象的话,那一定是java的Debug了,因为要开启Debug,是需要在启动参数中加入agent的,如 -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5001 限于篇幅原因,agent技术不在此展开,可以自行了解,目前只要明确其可以更改正在运行类的字节码即可,从而对程序进行观测和影响。

部分的小伙伴可能会提到,为何不利用jvm的机制直接加载Debug的agent呢?

  • 首先,有试过一下,但是attach失败了,推测是该agent只能启动时候进行指定;
  • 其次,Debug其实对性能损耗是比较大的,尤其是断点很多的时候;
  • 再者,在线上的宿主机或者容器临时开启一个端口,不知道运维大佬会不会放过你;

4.“代价”

对于所在企业内部尚未应用Arthas到生产环境的小伙伴而言,想要尝试使用那必定是要知悉其中风险滴,下边我们简要分析下:

  • 首先,你并不是第一个吃螃蟹的人,Arthas至今已经迭代了多个版本(阿里团队研发),并且很多知名企业都在使用。
  • 其次,由前文的启动示意可知,Arthas实际上就是运行在目标宿主jvm上的,因此一般也只会影响该jvm。
  • 再次,如果目标jvm的内存配置很小,那有可能会attach失败,或者由于频繁更新字节码,导致gc。
  • 最后,需要注意对宿主机的影响,当你把多个jvm进程启动在一个宿主机上时,如果使用Arthas的jvm出现快速写盘(如Arthas日志输出到文件,或者更改了日志级别)时,有可能导致宿主机io负载过高,cpu也是如此。

四、Arthas的命令分类

初步接触Arthas的时候,容易被其强大的功能和命令冲昏头脑,导致实际遇到问题时候,不知所措,所以初学者应当对功能和命令进行分类,以便梳理和记忆。 以下是本人对命令的理解和分类:(每个命令都可点击跳转到官方使用文档)

1.信息的观测&监控

a.观测具体的类、方法【重点】

信息的观测&监控

b.查看运行的状态&信息

查看运行的状态&信息

2.我想改变程序行为

改变程序行为

3.基础使用命令和日志处理命令

此部分命令较为简单直接,参阅官方文档即可

五、温馨提示

强烈推荐阅读Github Arthas上的 user-case:https://github.com/alibaba/arthas/issues?q=label%3Auser-case

1.表达式是可以调用静态方法的

经过简单的了解,我们都知道,Arthas的部分命令(【观测被动执行的方法】)是支持表达式的,表达式中除了预定义的几个参数外,也可以调用静态方法获取结果,进而执行其它操作。

a.使用 TraceId or Flow or Cookie 来过滤请求

在实践中,为了把单个请求的日志串联起来,往往会生成一个标识,有的称之为traceId,有的称之为流水flow,而这些标识往往都是可以通过静态方法来获取的,因此,只要所使用的系统中,具备客户端指定标识的能力时,我们就能在服务端准确地观测该请求。 如,在springboot搭建的web项目中,就可以这样获取cookie @org.springframework.web.context.request.RequestContextHolder@getRequestAttributes().getRequest().getCookies()

2.命令中使用到类名时,一般都是要使用全限定名的

  • 在使用 watch trace 等命令的时候,是需要指定类名和方法名的, 如 watch com.wingli.controller.DemoController demoMethod
  • 在使用 ognl 表达式的时候也是一样,如 ognl '@java.lang.System@out.println("hello")'

3.分布式下的Arthas

因为Arthas的使用对象是单个jvm进程,当你的应用是分布式的,并且使用的系统不具备将请求导向某台制定机子的时候,要想捕捉这个请求,则需要多个应用都启用Arthas,然后一个一个去执行对应的观测命令

4.关闭Arthas

如果所在的系统不是让Arthas常驻宿主应用,那么每次使用前都要进行启动,每次使用完都是需要进行关闭的,否则Arthas常驻jvm会消耗一定的资源,涉及的命令有

  • quit 退出本次连接,但宿主jvm内仍运行着arthas-server,只是退出了arthas-client
  • stop 退出arthas-server,并恢复增强过的类

5.重新连接Arthas

当因为某些原因退出了 arthas-client 的时候,也可以通过 telnet ip port 来连接上 arthas-server ,而没必要再次attach。

6.永远记得使用help

Arthas相关命令的help都写得很详细易懂,当你忘记了参数时,它可以帮助你

写在最后

Arthas目前应用广泛,相关的使用文章也非常多,并且官方也有收集整理使用案例,因此就不再重复写命令的使用和案例了。此文主要目的是简单了解Arthas能力的来源,以及提供Arthas命令的分类方式,为尚不熟练的小伙伴提供思路,以至于遇到问题不必浏览一次所有命令,再确认有没有自己想要的!

Arthas最好的学习资料就是官网上的上百个使用case,以及官网的在线教程!

文章目录
  1. 1. 一、初识Arthas
    1. 1.1. 1.使用前:日志满天下
    2. 1.2. 2.使用后:一个能打的都没有
  2. 2. 二、kotlin/jvm 也能用
  3. 3. 三、必备知识
    1. 3.1. 1.启动Arthas
    2. 3.2. 2.启动过程示意
    3. 3.3. 3.探针Javaagent
    4. 3.4. 4.“代价”
  4. 4. 四、Arthas的命令分类
    1. 4.1. 1.信息的观测&监控
      1. 4.1.1. a.观测具体的类、方法【重点】
      2. 4.1.2. b.查看运行的状态&信息
    2. 4.2. 2.我想改变程序行为
    3. 4.3. 3.基础使用命令和日志处理命令
  5. 5. 五、温馨提示
    1. 5.1. 1.表达式是可以调用静态方法的
      1. 5.1.1. a.使用 TraceId or Flow or Cookie 来过滤请求
    2. 5.2. 2.命令中使用到类名时,一般都是要使用全限定名的
    3. 5.3. 3.分布式下的Arthas
    4. 5.4. 4.关闭Arthas
    5. 5.5. 5.重新连接Arthas
    6. 5.6. 6.永远记得使用help
  6. 6. 写在最后