arthas

案例: 排查函数调用异常(watch)

Arthas在 watch/trace 等命令时,实际上是修改了应用的字节码,插入增强的代码。显式执行 reset 命令,可以清除掉这些增强代码。
现象
访问 http://localhost:61000/user/0 ,会返回500异常:
在Arthas里执行(进行监控)

watch com.example.demo.arthas.user.UserController * '{params, throwExp}' -x 2

当发送请求时,就会打印日志信息;可以查看到具体的报错信息
返回值表达式
在上面的例子里,第三个参数是返回值表达式,它实际上是一个ognl表达式,它支持一些内置对象:
loader
clazz
method
target
params
returnObj
throwExp
isBefore
isThrow
isReturn
watch命令参考文档
watch命令支持在第4个参数里写条件表达式,比如:

watch com.example.demo.arthas.user.UserController * returnObj 'params[0] > 100'

当访问 user/1 时,watch命令没有输出

当访问 user/101 时,watch会打印出结果。

watch命令支持按抛出异常进行过滤

watch com.example.demo.arthas.user.UserController * "{params[0],throwExp}" -e

watch命令支持按请求耗时进行过滤,比如:

watch com.example.demo.arthas.user.UserController * '{params, returnObj}' '#cost>200'

案例: 热更新代码(jad/mc/redefine)

  1. jad命令反编译UserController
 jad --source-only com.example.demo.arthas.user.UserController > /tmp/UserController.java
  1. 修改代码
  2. sc命令查找加载具体类(UserController)的具体ClassLoader,使用此类加载器重新编译加载代码
 sc -d *UserController | grep classLoaderHash
 classLoaderHash   1be6f5c3

请记下你的classLoaderHash,后面需要使用它。在这里,它是 1be6f5c3。

  1. 使用mc(Memory Compiler)命令来编译,并且通过-c或者–classLoaderClass参数指定ClassLoader
mc --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader /tmp/UserController.java -d /tmp
Memory compiler output:
/tmp/com/example/demo/arthas/user/UserController.class
Affect(row-cnt:1) cost in 346 ms

也可以通过mc -c /tmp/UserController.java -d /tmp,使用-c参数指定ClassLoaderHash:

mc -c 1be6f5c3 /tmp/UserController.java -d /tmp
  1. 再使用redefine命令重新加载新编译好的UserController.class:
$ redefine /tmp/com/example/demo/arthas/user/UserController.class
redefine success, size: 1

动态更新应用Logger Level

查找UserController的ClassLoader

sc -d com.example.demo.arthas.user.UserController | grep classLoaderHash
 classLoaderHash   1be6f5c3

用ognl获取logger

ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'

可以知道UserController@logger实际使用的是logback。可以看到level=null,则说明实际最终的level是从root logger里来的。

单独设置UserController的logger level

ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger.setLevel(@ch.qos.logback.classic.Level@DEBUG)'

再次获取UserController@logger,可以发现已经是DEBUG了:

ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@com.example.demo.arthas.user.UserController@logger'

修改logback的全局logger level
通过获取root logger,可以修改全局的logger level:

ognl --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader '@org.slf4j.LoggerFactory@getLogger("root").setLevel(@ch.qos.logback.classic.Level@DEBUG)'

案例: 排查logger冲突问题

案例: 获取Spring Context

tt -t 类 方法

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

使用tt命令从调用记录里获取到spring context

tt -i 1000 -w 'target.getApplicationContext()'

获取spring bean,并调用函数

案例: 排查HTTP请求返回401

trace javax.servlet.Filter *
stack javax.servlet.http.HttpServletResponse sendError 'params[0]==401'

案例: 排查HTTP请求返回404

trace javax.servlet.Servlet * > /tmp/servlet.txt

案例: 理解Spring Boot应用的ClassLoader结构

classloader -l

案例:查找Top N线程

查看5秒内的CPU使用率top n线程栈

thread -n 3 -i 5000
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值