arthas手册:
https://arthas.aliyun.com/doc/
https://www.yuque.com/arthas-idea-plugin
@RequestMapping("/trace/{name}")
@ResponseBody
public String traceE(@PathVariable String name) {
String bb=null;
if (StringUtils.isEmpty(name)) {
bb = "小帅哥";
} else {
bb = name + "小帅哥";
}
return arthasTestService.doTraceE(bb);
}
watch
当用watch来监视这个方法时:
watch com.wangji92.arthas.plugin.demo.controller.CommonController traceE '{params,returnObj,throwExp}' -n 5 -x 3 "params[0].equals('dd')" -v
只有满足name=dd的时候才进行监视
当输入其他值,为false
通过这个命令,直接可以直接触发一次调用
我随便调用一下这个contoller中的任意的方法,都会触发调watch的这个方法
Trace(跟踪源码很强)
备注:这个只会对于当前方法生效,不会调用方法中调用的方法。
如果要再调用下一个方法使用
trace -E xxxAclass|xxxBClass xxMethod|xxx2Method 这样的规则 没有先后顺序
不跳过jdk的方法 --skipJDKMethod false
trace -E com.wangji92.arthas.plugin.demo.controller.CommonController|com.wangji92.arthas.plugin.demo.service.ArthasTestService traceE|doTraceE -n 5
可以把下游的方法也打印出来
加上–skipJDKMethod false后,能把jdk的方法打印出来
trace -E com.wangji92.arthas.plugin.demo.controller.CommonController|com.wangji92.arthas.plugin.demo.service.ArthasTestService traceE|doTraceE -n 5 --skipJDKMethod false
获取spring context的信息
用sc -d 命令获取类的hash值
为了要获取springcontext值,需要提供一个类,由于这个spring context 是静态的,那么一定是可以通过ognl 获取的
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext context;
public ApplicationContext getApplicationContext() {
return context;
}
@Override
public void setApplicationContext(ApplicationContext ctx) {
context = ctx;
}
}
我们可以查看springcontext中加载的某个值,查看值的内容,所以能查看到springcontext中所有的属性,能查看属性的加载顺序
ognl -x 3 '#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#springContext.getEnvironment().getProperty("custom.name")' -c 71ce3642
获取ApplicationContext 后,能获取到对应的对象,然后调用对象的方法
@RequestMapping("/getRandomInteger")
@ResponseBody
public Integer getRandomInteger() {
return new Random().nextInt(1000);
}
ognl -x 3 '#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#springContext.getBean("commonController").getRandomInteger()' -c 9df3ac
TT
tt -t com.wangji92.arthas.plugin.demo.controller.CommonController getRandomInteger -n 5
-n 参数指定你需要记录的次数,当达到记录次数时 Arthas 会主动中断tt命令的记录过程,避免人工操作无法停止的情况
查看具体的信息
tt -i 1002
而有些场景下,这个调用不是这么好触发的,或者需要前端配合,解放你的沟通成本,这个时候只要通过
-p 参数。通过 --replay-times 指定 调用次数,通过 --replay-interval 指定多次调用间隔(单位ms, 默认1000ms)
$ tt -i 1002 -p
Classloader
可以看到通过这个命令classloader -l,我们能看到这个程序有6中类加载器。我们上面获取到的71ce3642,其实就是指向的org.springframework.boot.devtools.restart.classloader.RestartClassLoader
如果每个类没有被加载到jvm中,我们可以手工的加载这个类
@Slf4j
public class NotLoaderClass {
public static String NO_LOAD = "not load";
}
加载成功后,就可以通过springcontext获取到变量的值了
动态修改Log日志级别
可以看到这个类的日志级别为info
修改为debug后
能打印debug的日志了,这是这个类生效
如果要改变项目的日志级别,所有类打印都是debug级别了
logger --name ROOT --level debug
打印MyBatis SQL语句
改变某个Mapper的日志级别
logger --name sample.mybatis.mapper.HotelMapper --level debug
通过watch命令能查看正在执行的sql,可以加条件来过滤
watch org.apache.ibatis.mapping.BoundSql getSql '{params,returnObj,throwExp}' -n 5 -x 3
2.如果第一种方法不成功,使用下面命令
sc -d *Test 来获取Classloader
logger -c 31cefde0 --name root --level debug
线上问题排查
- thread 查看所有线程信息
- thread -n [显示的线程个数] ,就可以排列出 CPU 使用率 Top N 的线程
- thread-b 命令查看直接定位到死锁信息