Arthas是阿里巴巴开源的应用诊断利器,Apache Dubbo是阿里巴巴开源的高级RPC框架,如何使用Arthas来排查dubbo应用的问题?
下面分享一些使用Arthas排查Dubbo问题的经验。
dubbo-arthas-demo
所有的排查都是基于这个非常简单的一个应用,浏览器请求从Spring MVC到Dubbo Client,再发送到Dubbo Server。
Demo里有两个spring boot应用,先启动服务端server-demo
,再启动客户端client-demo
。
客户端:
服务器端:
Arthas快速开始
- https://alibaba.github.io/arthas/install-detail.html
启动后,会列出所有的java进程,选择1,然后回车,就会连接上 ServerDemoApplication
Dubbo线上服务引发异常,如何获取调用参数?
- https://alibaba.github.io/arthas/watch.html
当线上服务引发异常时,最着急的是什么参数导致了抛异常?
在demo里,访问http://localhost:8080/user/0,UserServiceImpl
就会引发一个异常,因为user id不合法。
在Arthas里执行,然后再次访问,就可以看到watch命令把参数和异常都打印出来了。
如何调试Dubbo服务代码?
- https://alibaba.github.io/arthas/redefine.html
在本地开发时,可能会用到热部署工具,直接改写代码,不需要重启应用。但是在线上环境,有没有方法直接动态调试代码?
在Arthas里,可以通过redefine
命令来达到线上不重启,动态更新代码的效果。
例如我们修改下UserServiceImpl
,用打印出具体的对象来:
本地编绎后,传到线上服务器,然后用命令来更新代码:
这样子更新成功之后,访问http://localhost:8080/user/1,在ServerDemoApplication
的控制台里就可以看到打印出了用户信息。
怎样动态修改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
在排查问题时,需要查看到更多的信息,如果可以把loggergrade修改为DEBUG
,就非常有帮助。
ognl
是apache开源的一个轻量级表达式引擎。下面通过Arthas里的ognl
命令来动态修改logger等级。
首先获取Dubbo里TraceFilter
的一个logger对象,看下它的实现类,可以发现是log4j。
再用sc
命令来查看具体从该哪个jar包里加载的:
可以看到log4j是通过slf4j代理的。
那么通过获取logger,再修改它的级别:
可以看到修改之后,root
logger的级别转化DEBUG
。
怎样减少测试小姐姐重复发请求的麻烦?
- https://alibaba.github.io/arthas/tt.html
在平时开发时,可能需要测试小姐姐发请求过来联调,但是我们在调试时,可能不小心直接跳过去了。这样子就尴尬了,需要测试小姐姐再发请求过来。
Arthas里提供了tt
命令,可以减少这种麻烦,可以直接重新请求。
上方的命令捕获到了3个请求。然后可以重新初始化请求:
Dubbo运行时有一些过滤器?耗时是多少?
- https://alibaba.github.io/arthas/trace.html
Dubbo运行时会加载很多的过滤器,那么一个请求会经过某种过滤处理,过滤里的耗时又是多少呢?
通过Arthas的trace
命令,可以很方便地知道Filter的信息,可以看到详细的调用栈和耗时。
Dubbo动态代理是怎样实现的?
- https://alibaba.github.io/arthas/jad.html
- com.alibaba.dubbo.common.bytecode.Wrapper
通过Arthas的jad
命令,可以看到Dubbo通过javaassist动态生成的Wrappr类的代码:
获取Spring上下文
除了上面介绍的一些排查技巧,下面分享一个获取Spring Context,然后“为所欲为”的例子。
在Dubbo里有一个扩展,把Spring Context保存到了里面。因此,我们可以通过命令获取到。
下上面的语句:
SpringExtensionFactory@contexts.iterator.next
获取到SpringExtensionFactory
里保存的spring context对象#context.getBean("userServiceImpl").findUser(1)
获取到userServiceImpl
再执行一次调用
总结
Arthas里的功能很强大,更多功能大家可以自行探索学习。
读后深有感触谢谢你们.茶壶说:“有些事,容不得你想不开。”
年纪大了,喝杯冰啤酒都想往里面加两个枸杞。喜欢这个风格博主 thank