线上Debug,学会Arthas拿捏所有bug

点击上方“Java基基”,选择“设为星标”

做积极的人,而不是积极废人!

每天 14:00 更新文章,每天掉亿点点头发...

源码精品专栏

 

来源:juejin.cn/post/

7021725088659701791


一、初识Arthas

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

1.使用前:日志满天下

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

  • 这个方法报错了,参数传了啥?打日志

  • 这个if为啥没进去?打两条日志

  • 这个方法执行了多少次?循环打日志

  • 请求耗时很慢,那个环节比较慢?花式打日志 当线上出现问题的时候,也是通过日志来定位,比较尴尬的是,日志加上去,发版,服务就需要重启,这样会导致一些问题:

  • 一是对服务有影响,该时刻请求会被中断,进而失败(当时没有摘流量这种操作)

  • 二是重启后问题现场已经被破坏了,无法复现问题

  • 三是日志过多,落盘会导致io升高,磁盘容量需求也变高,日志查询速度也变慢

  • 四是加一次日志往往还不能定位到问题,需要加几次

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

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

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

  • 想看方法的调用信息?Easy

  • 依赖包混乱,不知道实际运行用了哪个?So Easy

  • 怀疑线程在摸鱼?Very Easy

  • 热更新代码?比较麻烦,但可以

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

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

二、kotlin/jvm 也能用

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

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud

  • 视频教程:https://doc.iocoder.cn/video/

三、必备知识

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

5eec039322c6ec5f81352bd3b0112961.jpeg
启动过程示意
  • 通过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.观测具体的类、方法【重点】

2440971a2d179146ddf17fa6da013254.png

信息的观测&监控
b.查看运行的状态&信息

f0c4897205d5b6e29e4643320bc2e7d3.png

查看运行的状态&信息

2.我想改变程序行为

c1db1e84347c3205c0b5315a39798414.png

改变程序行为

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,以及官网的在线教程!



欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢

db3501d55915f7c8781858e97ffe2cf5.png

已在知识星球更新源码解析如下:

efa871a87bfda83a3a678b6bab57767e.jpeg

022190dfc1ca2be2582fb9c7d002bfff.jpeg

e5dddf8f51b5bf27929073935e0dd3f6.jpeg

b563456a65cef820219aff2beb9eb42f.jpeg

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 6W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值