天天看点

阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结

作者 | 汪小哥

Arthas 对于很多 Java 开发者来说,已经不可分割了,在我们日常开发、线上问题排查中扮演了非常重要的角色。作为小开发的我,日常需要排查线上运营同学提的各种 bug、各种线上问题诊断、日常运维、线上问题优化等等。

在刚来公司时,我是比较恐惧运维任务的,代码不熟悉、各种问题比较多...几乎崩溃的状态,运维的一周基本上没有干活,完全是全身心投入到运维的任务中,排查问题效率低下。

由于深刻体验到了这种奔溃,我一直想改变这种状态,直到 Arthas 的开源,让我在这种崩溃的状态中减轻了不少负担,同时也让我成为了同事们咨询 Arthas 排查问题的小帮手~~ 虽然使用 Arthas 特别方便,但在此过程中也遇到一些问题,作为问题咨询小帮手也感到有点不方便,因此才造就了 Arthas idea 插件的诞生。

阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结

目前 Arthas 官方的工具还不够简单,需要记住一些命令,特别是一些扩展性特别强的高级语法,比如 ognl 获取 spring context 为所欲为,watch、trace 不够简单,需要构造一些命令工具的信息,因此只需要一个能够简单处理字符串信息的插件即可使用。

当在处理线上问题的时候需要最快速、最便捷的命令,因此 Idea Arthas plugin 插件还是有存在的意义和价值的。---这个是最初编写这个插件的最核心的理由。

Arthas IDEA plugin 实践

Arthas 的功能点非常的多(详见下方大图),这里就不一一的讲解了,可以参考使用文档 ,不过最近一直在更新,使用文档中的命令名称可能有变化。

阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结

插件安装

下载 arthas idea 插件:

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

    Preferences

     -> 

    Plugins

  • Windows:

    Settings

    Plugins

Install Plugin form Disk... 导入插件

阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结

安装之后重启 IDEA 就可以愉快的使用啦!

获取 static 变量

首先要获取 classloader 的 hash 值,然后获取命令,这个是一个交互流程需要连贯性,后续只要是 static 的通过 static spring context 的都需要有这个交互的流程,连贯的,都在同一个界面进行操作.粘贴执行,然后获取结果即可。

这里的 classloader 的 hash 值缓存起来的
阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结
阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结

最后合并的脚本如下。

ognl  -x  3 '@com.wangji92.arthas.plugin.demo.controller.StaticTest@INVOKE_STATIC_NAME' -c 316bc132           

反射设置 static field

通过反射进行设置 static field ,参考:

https://github.com/WangJi92/arthas-idea-plugin/issues/1
阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结

填写你想要修改的值、默认根据类型设置默认值 Str->"" Long -> 0L 等等。

阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结
ognl -x 3  '#[email protected]@class.getDeclaredField("INVOKE_STATIC_FINAL"),#modifiers=#field.getClass().getDeclaredField("modifiers"),#modifiers.setAccessible(true),#modifiers.setInt(#field,#field.getModifiers() & [email protected]@FINAL),#field.setAccessible(true),#field.set(null,"设置的值")' -c 316bc132           

Spring Context Invoke

通过 spring context 进行调用 bean 的方法、字段的内容。

Static Spring Context Invoke Method Field

首页要设置一下 static spring context 的路径。

阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结
阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结

由于都是通过 ognl 调用 static 的 spring context 都需要 classloader,这个就是配置的 spring conetxt 的地址信息:

@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context 参考 demo 就需要配置这个地址。

ognl -x 3 '#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#springContext.getBean("commonController").getRandomInteger()' -c 316bc132           

Watch Spring Context Invoke Method Field

watch 这个是支持在 spring mvc 场景,通过 watch 间接的获取 spring context,需要出发一次接口的调用,可以参考 :

https://github.com/WangJi92/arthas-idea-plugin/issues/5
阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结
watch -x 3 -n 1  org.springframework.web.servlet.DispatcherServlet doDispatch '@org.springframework.web.context.support.WebApplicationContextUtils@getWebApplicationContext(params[0].getServletContext()).getBean("commonController").getRandomInteger()'           

TimeTunnel Spring Context Invoke Method Field

这个是参考了横云断岭的 arthas 通过 tt 获取 spring context 为所欲为 ,可以参考这个文档:

https://github.com/WangJi92/arthas-idea-plugin/issues/4

这里做了些什么?将整个连贯了起来,不需要记住参数信息,然后对于调用的参数进行简单的默认封装,复杂的参数场景不支持,需要手动拼接。

阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结

记录获取 spring context

tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod           

然后根据这个 target 获取 spring context 调用方法

tt -w 'target.getApplicationContext().getBean("commonController").getRandomInteger()' -x 3 -i 1000           

获取某个 spring 环境变量

获取 spring 环境变量这里依托,static spring context ,当然这个 watch 、和 tt 获取 spring context 的场景也是支持的。在线上环境、测试环境程序多复杂,你怎么知道环境中的变量一定是你配置的?在 nacos 等等配置中心的场景,估计手速慢了一点点,可能就没有上去,这个时候就有这种需求获取当前的环境变量。选中变量,然后右键执行命令。由于使用静态的 static spring context 依然需要 classloader 的值。这里已经基本上是 arthas 的上层应用啦。

阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结
阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结
ognl -x 3 '#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#springContext.getEnvironment().getProperty("custom.name")' -c 316bc132           

获取全部的 spring 环境变量

比较优先级,最前面的一定优先级最高,你一定被 spring 的各种优先级顺序搞晕了,那么怎么办呢?arthas idea plugin 支持获取当前的全部的环境变量,依次打印出来,这样就可以了解优先级,特别是接入了 nacos、diamond 等远程的配置中心,实现不一样肯定更晕了。

参考文档:

https://blog.csdn.net/xunjiushi9717/article/details/94050139
阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结
阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结
ognl -x 3 '#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#allProperties={},#standardServletEnvironment=#propertySourceIterator=#springContext.getEnvironment(),#propertySourceIterator=#standardServletEnvironment.getPropertySources().iterator(),#propertySourceIterator.{#key=#this.getName(),#allProperties.add("                "),#allProperties.add("------------------------- name:"+#key),#this.getSource() instanceof java.util.Map ?#this.getSource().entrySet().iterator.{#key=#this.key,#allProperties.add(#key+"="+#standardServletEnvironment.getProperty(#key))}:#{}},#allProperties' -c 316bc132           

TimeTunnel Tt

方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测(可以重新触发,周期触发,唯一缺点对于 ThreadLocal 信息丢失[隐含参数]、引用对象数据变更无效),这个方便二次触发,特别是自己调试不方便的情况下记录下来,二次触发、周期触发,不过自从段岭大神 tt 为所欲为之后都被带偏了。这里 arthas 插件做了一些什么?增加了二次触发的一些常用的命令,不让使用者愁于记忆,整个过程更加的具有连贯性。

阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结
阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结

stack 堆栈

获取方法从哪里执行的调用栈(用途:源码学习调用堆栈,了解调用流程) 这个是非常好用的功能,对于喜欢乐于排查问题的小伙伴真是福音,arthas idea 插件只是修改的命令的集成,之前也处理自己编码过程中的问题,源码、问题排查技巧-Java Debug and Arthas:

https://blog.csdn.net/u012881904/article/details/104591529
stack com.wangji92.arthas.plugin.demo.controller.CommonController getRandomInteger -n 5           

Decompile Class Jad

反编译方法、类的源码, 有时候需要查看提交的代码是否上线呢?这个功能就非常的友好。

参考文档:[

https://github.com/WangJi92/arth!

as-idea-plugin/issues/2](

https://github.com/WangJi92/arthas-idea-plugin/issues/2)
阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结
jad --source-only com.wangji92.arthas.plugin.demo.controller.CommonController getRandomInteger           

watch、trace

增加了默认参数、默认展开的层级限制次数,使用者不用知道这些核心的参数,简单的使用就好了,要使用更加的高级的自己help 一下就知道了。

watch com.wangji92.arthas.plugin.demo.controller.CommonController getRandomInteger '{params,returnObj,throwExp}' -n 5 -x 3
trace com.wangji92.arthas.plugin.demo.controller.CommonController getRandomInteger -n 5           

trace -E(层级的打印 trace)

trace -E 自己构造起来非常的麻烦,通过界面操作简化了一下,需要观察多个类、多个方法的场景。选择你需要的场景继续添加即可。

阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结
trace -E com.wangji92.arthas.plugin.demo.controller.CommonController|com.wangji92.arthas.plugin.demo.service.ArthasTestService traceE|doTraceE -n 5           

Heap Dump

打印堆栈,有点类似 jmap -dump:format=b,file=/temp/dump.hprof pid 下载下来使用 MAT 分析即可。

heapdump  /tmp/dump.hprof 打印堆栈信息            
阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结

特殊用法链接

这个必须要说一下,这个特殊用法的链接在线上自己束手无措的时候可以查看一下,非常有用。

阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结
阿里开源的那个牛X的问题排查工具——Arthas,推出IDEA插件了!Arthas IDEA plugin 实践总结

对于通过 spring context 调用方法说明

通过 spring context 调用复杂的方法其实是不支持的,由于这个操作起来不方便,还是必须手工处理一下。

比如这里的 Map names 的处理方式可以借鉴一下子。

更多可以参考 demo:

https://github.com/WangJi92/arthas-plugin-demo
/**
     * 复杂参数调用 场景
     * static spring context
     * ognl -x 3 '#user=new com.wangji92.arthas.plugin.demo.controller.User(),#user.setName("wangji"),#user.setAge(27L),#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#springContext.getBean("commonController").complexParameterCall(#{"wangji":#user})' -c e374b99
     *
     * watch get spring context 备注 需要调用一次方法
     * watch -x 3 -n 1  org.springframework.web.servlet.DispatcherServlet doDispatch '#user=new com.wangji92.arthas.plugin.demo.controller.User(),#user.setName("wangji"),#user.setAge(27L),@org.springframework.web.context.support.WebApplicationContextUtils@getWebApplicationContext(params[0].getServletContext()).getBean("commonController").complexParameterCall(#{"wangji":#user})'
     *
     * tt get spring context ,only first get time index ok
     * tt -w '#user=new com.wangji92.arthas.plugin.demo.controller.User(),#user.setName("wangji"),#user.setAge(27L),target.getApplicationContext().getBean("commonController").complexParameterCall(#{"wangji":#user})' -x 3 -i 1000
     * @return
     */
    @RequestMapping("complexParameterCall")
    @ResponseBody
    public String complexParameterCall(@RequestBody  Map<String, User> names) {
        if (names == null) {
            return "EMPTY";
        }
        return names.toString();
    }           

总结

本文简单介绍了 Arthas IDEA 插件的安装与使用技巧,该插件解放了大家对于 Arthas 使用的一些记忆、机械性的重复工作,欢迎大家试用!

Arthas 官方举行了征文活动,于 3 月 26 日—— 4 月 26 日举办,如果你有:

  • 使用 Arthas 排查过的问题
  • 对 Arthas 进行源码解读
  • 对 Arthas 提出建议
  • 不限,其它与 Arthas 有关的内容

 欢迎参加征文活动,还有奖品拿哦~

点击了解详情

阿里巴巴云原生 关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的技术圈。”