做者 | 汪吉html
【Arthas 官方社区正在举行征文活动,参加即有奖品拿~点击投稿】java
1、入门步骤
1. 安装
https://arthas.gitee.io/install-detail.htmlgit
上述命令会下载启动脚本文件 as.sh
到当前目录:github
curl -L https://alibaba.github.io/arthas/install.sh | sh
orweb
as.sh 启动:spring
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
2. 在线教程体验
https://alibaba.github.io/arthas/arthas-tutorials?language=cnexpress
固然也能够本身本地体验一下~本身经过下载一个 arthas-idea-plugin 的体验 demo 直接本地上手。apache
https://github.com/WangJi92/arthas-plugin-demo性能优化
全局命令说明
- -x 是展现结果属性遍历深度,默认为 1
- -n 是执行的次数 ,q 退出
- -c classloader 的hash值
- 退出 q ,关闭 stop
3. 了解最经常使用的trace、watch的功能
watch和trace 是arthas 诊断中对于开发人员解决线上的问题最经常使用的功能!bash
trace
基本示例
trace com.wangji92.arthas.plugin.demo.controller.CommonController getRandomInteger -n 5 '1==1'
https://arthas.gitee.io/trace.html
- 性能优化~
- 调用的这个方法,走的具体流程是咋样的!能够经过调用链看出来。
- 有异常了能够查看异常的堆栈。
高级的功能
trace命令只会trace匹配到的函数里的子调用,并不会向下trace多层。由于trace是代价比较贵的,多层trace可能会致使最终要trace的类和函数很是多。
trace -E xxxClassA|xxxClassB method1 | method2
trace -E com.wangji92.arthas.plugin.demo.controller.CommonController|com.wangji92.arthas.plugin.demo.service.ArthasTestService traceE|doTraceE -n 5 '1==1'
watch
https://arthas.gitee.io/watch.html
wathc 从字面上理解就是观察值的信息,能够查看入参、返回值、异常、能够执行表达式获取静态变量、target.xxx调用目标实施的字段、方法等等都行~只要你想获得没有作不到的~
基本示例
watch com.wangji92.arthas.plugin.demo.controller.CommonController traceE '{params,returnObj,throwExp}' -n 5 -x 3 '1==1'
四、arthas 表达式核心变量
public class Advice { private final ClassLoader loader; private final Class<?> clazz; private final ArthasMethod method; private final Object target; private final Object[] params; private final Object returnObj; private final Throwable throwExp; private final boolean isBefore; private final boolean isThrow; private final boolean isReturn; // getter/setter }
从watch 和 trace 中看到 后面的 '1==1' 执行的是一个条件表达式 当值为true 的时候经过执行了一个ognl 表达式 ,watch 观察 params,returnObj,throwExp 入参、返回值、是否异常 这个也是一个表达式,那么这个究竟是咋回事?
spring el 表达式
没有学习过ognl 使用多年的spring 必定知道他的el 表达式,el 表达式中也有一种概念叫作【Context 上下文,和表达式】 以下所示,由于有了simple这个上下文 才能解析 "booleanList[0]" 这个脚本的含义~ 这个很熟悉,很好理解,那么ognl 表达式同样不难了。
class Simple { public List<Boolean> booleanList = new ArrayList<Boolean>(); } Simple simple = new Simple(); simple.booleanList.add(true); StandardEvaluationContext simpleContext = new StandardEvaluationContext(simple); // false is passed in here as a string. SpEL and the conversion service will // correctly recognize that it needs to be a Boolean and convert it parser.parseExpression("booleanList[0]").setValue(simpleContext, "false"); // b will be false Boolean b = simple.booleanList.get(0);
ognl 表达式
arthas 也是同样的,只是使用了一个叫作ognl的脚本,核心变量就是他的上下文,能够直接获取到这些字段。watch 观察的这几个字段 params,returnObj,throwExp 也就是咱们所谓的上下文的概念,观察参数、返回值、和异常的信息。
以下是arthas 源码中 表达式评估和watch 观察值执行的代码!Advice 就是一个上下文,这里还增长了一个变量 const。知道了这些那不是很简单??
com.taobao.arthas.core.advisor.ReflectAdviceListenerAdapter#isConditionMet
/** * 判断条件是否知足,知足的状况下须要输出结果 * @param conditionExpress 条件表达式 * @param advice 当前的advice对象 * @param cost 本次执行的耗时 * @return true 若是条件表达式知足 */ protected boolean isConditionMet(String conditionExpress, Advice advice, double cost) throws ExpressException { return StringUtils.isEmpty(conditionExpress) || ExpressFactory.threadLocalExpress(advice).bind(Constants.COST_VARIABLE, cost).is(conditionExpress); } protected Object getExpressionResult(String express, Advice advice, double cost) throws ExpressException { return ExpressFactory.threadLocalExpress(advice) .bind(Constants.COST_VARIABLE, cost).get(express); }
表达式实践
arthas 群常常有人问重载方法如何判断,无非就是评估条件? 参数的个数、第一个参数是什么?返回值的类型等等均可以做为你评估的条件。以下的watch 前面的一段是观察的值、后面这一段是表达式评估 ,知足了条件才执行。
入参长度大于0
watch com.wangji92.arthas.plugin.demo.controller.CommonController traceE '{params,returnObj,throwExp}' -n 5 -x 3 'params.length >0'
返回值为String 且长度大于5
watch com.wangji92.arthas.plugin.demo.controller.CommonController traceE '{params,returnObj,throwExp}' -n 5 -x 3 'returnObj instanceof java.lang.String && returnObj.length>5'
条件表达式+异步任务
- 只有特定的场景才会有bug ,如何排查bug?
- 一天只出现一两次如何解决?
条件表达式主要是用来过滤使用,好比某些场景只是在特定的参数才会出现,肯能会花费不少的时间去等待,这个时候可使用条件表达式过滤 +异步任务更多参考博客
五、ognl 表达式
https://arthas.gitee.io/ognl.html 从上面看,ognl 在watch、trace上面无所不能啊,其实还有tt 也是 使用ognl 表达式执行逻辑的. @xxxClas@xxxStaticField 是静态变量的语法糖 ognl的,好好看一下官方的文档。OGNL特殊用法请参考:https://github.com/alibaba/arthas/issues/71
获取静态变量
静态变量因为 一个jvm 中可能被多个classloader加载,jvm 认定为一个实例是一个classloader加载哦,因此须要知道当前静态类的hash 值(sc -d com.wangji92.arthas.plugin.demo.controller.StaticTest)能够经过这个命令获取。
ognl -x 3 '@com.wangji92.arthas.plugin.demo.controller.StaticTest@INVOKE_STATIC_DOUBLE' -c e374b99
调用spring 方法?
watch 执行ognl 语法中获取spring context 而后进行调用bean的方法
watch -x 3 -n 1 org.springframework.web.servlet.DispatcherServlet doDispatch '@org.springframework.web.context.support.WebApplicationContextUtils@getWebApplicationContext(params[0].getServletContext()).getBean("commonController").getRandomInteger()'
ognl 执行静态的一个spring context 而后调用bean 的方法
ognl -x 3 '#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#springContext.getBean("commonController").getRandomInteger()' -c e374b99
有没有起飞的感受,无所不能!前提是你要掌握一些ognl的一些简单的语法!
六、完毕
对于线上排查问题,我感受这几个命令够你用了,还有一些其余的反编译、火焰图、.. 时间隧道、logger 等级修改,jvm环境信息等等感受是有频率都没有上面的高,毕竟jvm信息有专门的监控~即便没有arthas 你也能够找到更好的工具去分析堆栈,jvm故障。
一些特殊的用户案列值得学习思考: https://github.com/alibaba/arthas/issues?q=label%3Auser-case
完了? 啊?这么多命令 记不住啊 还有一些高级的ognl的语法凉了... 让你获取一下全部的spring的环境变量咋办?trace、watch 这两个命令我尚未体验够呢?更加高级的让我如何是好啊!好了,请看下文。
2、进阶
前提
前提是你对于arthas 有了大概的理解,基本上的命令都有点概念了,ognl 简单的语法可以看懂了.. 简单的条件表达式会用了。 以前咱们所过arthas的命令这么多 要记住小本本少不了啊!难受想哭~ 不要急,汪小哥来给你解决问题!
目前Arthas 官方的工具还不够足够的简单,须要记住一些命令,特别是一些扩展性特别强的高级语法,好比ognl获取spring context 随心所欲,watch、trace 不够简单,须要构造一些命令工具的信息,所以只须要一个可以简单处理字符串信息的插件便可使用。当在处理线上问题的时候须要最快速、最便捷的命令,所以arthas idea 插件仍是有存在的意义和价值的。
arthas idea plugin
这个插件的意义不是处理协议层面的问题,主要解决命令生成的问题,因为工程在idea 里面管理,你想一想你要watch 哪一个类,这个插件是知道的,帮助你更方便、更加快捷的构建命令。使用arthas idea 插件 这一点必定要理解哦!主要解决你如何构造命令的问题! 更多查看文档
解决的问题
- spring 环境变量优先级问题
- 获取静态变量
- 火焰图集成
- logger 命令集成
- 反编译集成
- trace -E 集成
- tt 集成
....... 基本上你可以在arths 上面看到的功能都集成到了这个上面!直接在idea 里面搜索arths idea 便可安装。
经常使用特殊用法问题
静态变量
能够直接获取 ognl 获取
ognl -x 3 '@com.wangji92.arthas.plugin.demo.controller.StaticTest@INVOKE_STATIC_DOUBLE' -c e374b99
能够经过watch 获取 (光标放置在字段上)
watch com.wangji92.arthas.plugin.demo.controller.StaticTest * '{params,returnObj,throwExp,@com.wangji92.arthas.plugin.demo.controller.StaticTest@INVOKE_STATIC_DOUBLE}' -n 5 -x 3 '1==1'
通常的变量
能够经过spring context.getBean().field 获取(这个是要配置一个静态的spring context 看使用文档)
tt 、watch 也是能够的哦~ 同样的原理
ognl -x 3 '#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#springContext.getBean("staticTest").filedValue' -c e374b99
watch 获取 放置在字段上便可
watch com.wangji92.arthas.plugin.demo.controller.StaticTest * '{params,returnObj,throwExp,target.filedValue}' -n 5 -x 3 'method.initMethod(),method.constructor!=null || !@java.lang.reflect.Modifier@isStatic(method.method.getModifiers())'
选择的配置项的值
springContext.getEnvironment() (这个是要配置一个静态的spring context 看使用文档)
ognl -x 3 '#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#springContext.getEnvironment().getProperty("custom.name")' -c e374b99
获取全部的配置项的值
watch 获取spring context tt 、static 也是能够的哦~ 同样的原理
watch -x 3 -n 1 org.springframework.web.servlet.DispatcherServlet doDispatch '#springContext=@org.springframework.web.context.support.WebApplicationContextUtils@getWebApplicationContext(params[0].getServletContext()),#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'
视频
有兴趣能够看一下视频~ 操做起来更流畅,基本上不用记忆啥。 arthas 入门到精通最佳实践
3、更多
还想了解更多关于arthas-idea-plugin 的内容能够联系我 能够经过 右键查看arthas-idea-help 找到代码地址和使用说明文档,更重要的是提一下好的idea 让arthas的使用更加的方便哦!插件地址: https://plugins.jetbrains.com/plugin/13581-arthas-idea
Arthas 征文活动火热进行中
Arthas 官方正在举行征文活动,若是你有:
- 使用 Arthas 排查过的问题
- 对 Arthas 进行源码解读
- 对 Arthas 提出建议
- 不限,其它与 Arthas 有关的内容
欢迎参加征文活动,还有奖品拿哦~点击投稿
“阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,作最懂云原生开发者的公众号。”