当Dubbo遇上Arthas - 排查问题的实践

Posted 阿里云云栖号

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当Dubbo遇上Arthas - 排查问题的实践相关的知识,希望对你有一定的参考价值。

Apache Dubbo是Alibaba开源的高性能RPC框架,在国内有非常多的用户。


  • Github:https://github.com/apache/incubator-dubbo

  • 文档:http://dubbo.incubator.apache.org/zh-cn/


Arthas是Alibaba开源的应用诊断利器,9月份开源以来,Github Star数三个月超过6000。


  • Github:https://github.com/alibaba/arthas

  • 文档:https://alibaba.github.io/arthas/


当Dubbo遇上Arthas,会碰撞出什么样的火花呢?下面来分享Arthas排查Dubbo问题的一些经验。


dubbo-arthas-demo


下面的排查分享基于这个dubbo-arthas-demo,非常简单的一个应用,浏览器请求从Spring MVC到Dubbo Client,再发送到Dubbo Server。


Demo里有两个spring boot应用,可以先启动server-demo,再启动client-demo。


  • https://github.com/hengyunabc/dubbo-arthas-demo



Client端:


当Dubbo遇上Arthas - 排查问题的实践


Server端:


当Dubbo遇上Arthas - 排查问题的实践


Arthas快速开始


  • https://alibaba.github.io/arthas/install-detail.html


当Dubbo遇上Arthas - 排查问题的实践


启动后,会列出所有的java进程,选择1,然后回车,就会连接上ServerDemoApplication


当Dubbo遇上Arthas - 排查问题的实践


Dubbo线上服务抛出异常,怎么获取调用参数?


  • https://alibaba.github.io/arthas/watch.html


当线上服务抛出异常时,最着急的是什么参数导致了抛异常?


在demo里,

访问http://localhost:8080/user/0,UserServiceImpl就会抛出一个异常,因为user id不合法。


在Arthas里执行 watch com.example.UserService * -e -x 2 '{params,throwExp}' ,然后再次访问,就可以看到watch命令把参数和异常都打印出来了。


当Dubbo遇上Arthas - 排查问题的实践


怎样线上调试Dubbo服务代码?


  • https://alibaba.github.io/arthas/redefine.html


在本地开发时,可能会用到热部署工具,直接改代码,不需要重启应用。但是在线上环境,有没有办法直接动态调试代码?比如增加日志。


在Arthas里,可以通过redefine命令来达到线上不重启,动态更新代码的效果。


比如我们修改下UserServiceImpl,用System.out打印出具体的User对象来:


当Dubbo遇上Arthas - 排查问题的实践


本地编绎后,

server-demo/target/classes/com/example/UserServiceImpl.class

传到线上服务器,然后用redefine命令来更新代码:


当Dubbo遇上Arthas - 排查问题的实践


这样子更新成功之后,访问 http://localhost:8080/user/1,在ServerDemoApplication的控制台里就可以看到打印出了user信息。


怎样动态修改Dubbo的logger级别?


  • https://alibaba.github.io/arthas/ognl.html

  • https://alibaba.github.io/arthas/sc.html

  • https://commons.apache.org/proper/commons-ognl/language-guide.html


在排查问题时,需要查看到更多的信息,如果可以把logger级别修改为DEBUG,就非常有帮助。


ognl是apache开源的一个轻量级表达式引擎。下面通过Arthas里的ognl命令来动态修改logger级别。


首先获取Dubbo里TraceFilter的一个logger对象,看下它的实现类,可以发现是log4j。


当Dubbo遇上Arthas - 排查问题的实践


再用sc命令来查看具体从哪个jar包里加载的:


当Dubbo遇上Arthas - 排查问题的实践


可以看到log4j是通过slf4j代理的。


那么通过org.slf4j.LoggerFactory获取root logger,再修改它的level:


当Dubbo遇上Arthas - 排查问题的实践


可以看到修改之后,root logger的level变为DEBUG。


怎样减少测试小姐姐重复发请求的麻烦?


  • https://alibaba.github.io/arthas/tt.html


在平时开发时,可能需要测试小姐姐发请求过来联调,但是我们在debug时,可能不小心直接跳过去了。这样子就尴尬了,需要测试小姐姐再发请求过来。


Arthas里提供了tt命令,可以减少这种麻烦,可以直接重放请求。


当Dubbo遇上Arthas - 排查问题的实践


上面的tt -t命令捕获到了3个请求。然后通过tt --play可以重放请求:


当Dubbo遇上Arthas - 排查问题的实践


Dubbo运行时有哪些Filter? 耗时是多少?


  • https://alibaba.github.io/arthas/trace.html


Dubbo运行时会加载很多的Filter,那么一个请求会经过哪些Filter处理,Filter里的耗时又是多少呢?


通过Arthas的trace命令,可以很方便地知道Filter的信息,可以看到详细的调用栈和耗时。


当Dubbo遇上Arthas - 排查问题的实践


Dubbo动态代理是怎样实现的?


  • https://alibaba.github.io/arthas/jad.html

  • com.alibaba.dubbo.common.bytecode.Wrapper


通过Arthas的jad命令,可以看到Dubbo通过javaassist动态生成的Wrappr类的代码:


当Dubbo遇上Arthas - 排查问题的实践


获取Spring context


除了上面介绍的一些排查技巧,下面分享一个获取Spring Context,然后“为所欲为”的例子。


在Dubbo里有一个扩展

com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory,把Spring Context保存到了里面。


因此,我们可以通过ognl命令获取到。



  • SpringExtensionFactory@contexts.iterator.next 获取到SpringExtensionFactory里保存的spring context对象

  • #context.getBean("userServiceImpl").findUser(1) 获取到userServiceImpl再执行一次调用


只要充分发挥想像力,组合Arthas里的各种命令,可以发挥出神奇的效果。


总结


本篇文章来自杭州Dubbo Meetup的分享《当DUBBO遇上Arthas - 排查问题的实践》,希望对大家线上排查Dubbo问题有帮助。


end

更多精彩

以上是关于当Dubbo遇上Arthas - 排查问题的实践的主要内容,如果未能解决你的问题,请参考以下文章

中原银行 Arthas 实践之路

Java 线上问题排查神器 Arthas 快速上手与原理浅谈

Java诊断利器Arthas优雅排查生产环境

java生产环境调试问题排查神器arthas(阿里中台开源的)

线上问题排查利器Arthas

阿里开源那个牛哄哄问题排查工具竟然不会用?最佳实践来了!