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

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