Arthas 排查线上问题的一个利器

问题

公司接了一个二次开发兼维护的Spring Cloud的项目,输出异常日志就打印了exception.msg(),没有输出 e.printStackTrace(),比如抛出了一个NullPointException,就输出了一个java.lang.NullPointerException,具体哪一行报错,也没输出。因为是线上的代码,不像测试环境,可以随意更新代码。这时候 arthas 就上场了。

安装

下载 arthas-boot.jar ,然后用 java -jar 的方式启动:

curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar

简单使用

创建一个简单的spring-boot项目

@RestController
public class DemoController {

    @RequestMapping("login")
    public String login(String name,String pwd){
        System.out.println("name:"+name+" pwd:"+pwd);
        return "success";
    }
}

启动项目成功后,启动 arthas:

java -jar arthas-boot.jar

输出

* [1]: 57824 org.jetbrains.jps.cmdline.Launcher
  [2]: 57826 com.slf.arthas.Application
  [3]: 56978 org.jetbrains.idea.maven.server.RemoteMavenServer36
  [4]: 10542 com.intellij.idea.Main
  [5]: 57919 org.jetbrains.jps.cmdline.Launcher
  [6]: 15823 com.intellij.database.remote.RemoteJdbcServer

因为我这边启动的 idea,所以有几个关于 idea 的程序。我们选择 2 ,选择自己的项目。

watch

让你能方便的观察到指定方法的调用情况。能观察到的范围为:返回值、抛出异常、入参

参数名称 参数说明
class-pattern 类名表达式匹配
method-pattern 方法名表达式匹配
express 观察表达式
condition-express 条件表达式
[b] 方法调用之前观察
[e] 方法异常之后观察
[s] 方法返回之后观察
[f] 方法结束之后(正常返回和异常返回)观察
[E] 开启正则表达式匹配,默认为通配符匹配
[x:] 指定输出结果的属性遍历深度,默认为 1

观察方法出参和返回值

[arthas@57826]$ watch com.slf.arthas.controller.DemoController login '{params,returnObj,throwExp}' -x 3
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 24 ms, listenerId: 3

我们请求一下接口

curl http://localhost:8080/login?name=张三&pwd=123456

查看窗口输出

ts=2020-08-31 20:29:36; [cost=0.343274ms] result=@ArrayList[
    @Object[][
        @String[张三],
        @String[123456],
    ],
    @String[success],
    null,
]

我们可以看到,请求时间[ts],请求接口消耗时间[cost],请求参数和返回结果。

jad

反编译指定已加载类的源码

[arthas@57826]$ jad com.slf.arthas.controller.DemoController

有时候,一个java类里面的方法很多,我这时候只想看某个方法的代码

[arthas@57826]$ jad com.slf.arthas.controller.DemoController login

那我能不能在线改代码呢?也可以,arthas都帮你想到了。

# 将代码反编译,并且把编译后的代码保存到 /tmp/ 目录下
[arthas@57826]$ jad --source-only com.slf.arthas.controller.DemoController > /tmp/DemoController

并开启一个窗口,编辑代码

$ vim /tmp/DemoController

加一段代码 int i = 1/0;

使用 mc 命令编译修改后的 DemoController.java

[arthas@57826]$ mc /tmp/DemoController -d /tmp
Memory compiler output:
/tmp/com/slf/arthas/controller/DemoController.class

使用redefine命令,因为可以热更新代码

[arthas@57826]$ redefine /tmp/com/slf/arthas/controller/DemoController.class 
redefine success, size: 1, classes:
com.slf.arthas.controller.DemoController

当我们再次请求接口的时候

抛出了异常

如果我把异常捕获了,那如何查询错误呢?

只输出一个 / by zero, 在不知道代码的情况下 ,很难找到出错的地方。

[arthas@57826]$ watch com.slf.arthas.controller.DemoController login '{params,returnObj,throwExp}' -x 3

参考

https://arthas.aliyun.com/doc/

https://my.oschina.net/u/3568600/blog/3071534

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章