alibaba / arthas

Alibaba Java Diagnostic Tool Arthas/Alibaba Java诊断利器Arthas
https://arthas.aliyun.com/
Apache License 2.0
35.49k stars 7.46k forks source link

使用Arthas显式执行代码,避免重启应用,10倍提升本地研发效率 #1823

Closed liuzhiguo630 closed 1 year ago

liuzhiguo630 commented 3 years ago

(用户案例)

前提

本方法最适用于 Spring Boot 项目。

谁拖垮了效率?

本地开发时有两个操作最耗时:

  1. 每次代码变更都要重启一次项目,重启的时间相对较长。
  2. 代码深层次的一个方法,也需要有类似 HTTP 的触发入口一层一层调用过来,这是非常麻烦的事。

所以我在寻找一种可以不停机的开发方法,所有变更都能随时生效,代码随写随测。

探索

代码热变更方面,我使用了久负盛名的 IDEA 插件 JRebel。该插件可以做到绝大部分的新增/修改代码,安装使用方式可以在网上搜索。

但有了 JRebel 之后,我发现仍然很难调用看到的方法,如果通过 HTTP 接口调用过来很麻烦,过程很长,并且前后的一些操作的结果也是我不想要的。再比如写着写着突然对某个资源的响应内容不确定。 我希望能随时调用看到的每一个方法。后来看了一些 arthas 的 user case 和文档,大脑中最后几块拼图也终于拼上了。

准备工作

随意调用方法,其实是指 Spring 上下文中的方法。否则直接写 main 方法或 Tester 代码就可以随写随测。以 Spring 的上下文进行调用才是我们想要的。以下是准备工作:

  1. 安装 IDEA Arthas 插件:https://arthas.aliyun.com/doc/idea-plugin.html
  2. 项目中增加依赖 Arthas Spring Boot Starterhttps://arthas.aliyun.com/doc/spring-boot-starter.html ,担心安全问题的话可以只在本地开启,其他环境配置 spring.arthas.enabled = false
  3. 代码中提供获取 Spring ApplicationContext 的变量的方法,参考 https://github.com/WangJi92/arthas-plugin-demo/blob/master/src/main/java/com/wangji92/arthas/plugin/demo/common/ApplicationContextProvider.java,并配置好插件获取 Spring Context 的路径: 截屏2021-06-14 下午1 39 34

开始起飞

使用 JRebel 的方式启动项目,启动后浏览器打开 Arthas 控制台 http://localhost:8563 ,在要调用的方法上选择复制Static Spring Context Invoke Method Field

截屏2021-06-14 下午1 44 03

随后到 Arthas 控制台粘贴即可:

截屏2021-06-14 下午1 46 21 截屏2021-06-14 下午1 46 30

整个开发过程中 Arthas 控制台不用关,随时想测某个方法时,复制命令 -> 控制台执行 -> 观察 即可。

此方法对以下一些场景有奇效:

  1. XXL-Job 任务执行。本地不希望任务在跑,就可以在启动时关闭任务注册功能。测试时也可以不依赖 xxl-job admin 随时调试任务。
  2. Dubbo 服务。不用模拟客户端或者泛化调用之类的,直接用 arthas 整。Arthas 命令不方便设置复杂的入参,这种情况可以在方法中自行覆盖参数,用 JRebel 热更新一下就行。
zxfxpower commented 2 years ago

不用JRebel启动,获取的context就是null。

liuzhiguo630 commented 2 years ago

不用JRebel启动,获取的context就是null。 这个应该跟 JRebel 没关系,context 是在 arthas idea 里配好的。你看下来 ognl 命令里的 context 路径对不对。

zxfxpower commented 2 years ago

不用JRebel启动,获取的context就是null。 这个应该跟 JRebel 没关系,context 是在 arthas idea 里配好的。你看下来 ognl 命令里的 context 路径对不对。

试了好多次都是这样,用JRebel启动才行 工程:https://github.com/WangJi92/arthas-plugin-demo.git ognl setting:@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context 方法调用:ognl -x 3 '#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#springContext.getBean("commonController").userOgnlX()'

另外运行环境如下: java 9 macos idea

ShuChangCloud commented 2 years ago

大佬 遇到另外一个问题 就是用jrebel的debug模式启动后, 是可以使用TT watch trace等命令的, 可是一改代码, jrebel重新reload以后, 再次使用这些命令后就会报Enhance error! exception: java.lang.NoClassDefFoundError: class names don't match这个错误。 请问下有什么好的解决方案吗

ZhangMuZhiYa commented 1 year ago

cool

Raxcl commented 2 weeks ago

不错不错,亲测可用