Alibaba應用診斷利器Arthas 3.0.5版本釋出:提升全平臺使用者體驗

橫雲斷嶺發表於2018-11-29

Arthas從9月份開源以來,受到廣大Java開發者的支援,Github Star數三個月超過6000,非常感謝使用者支援。同時使用者給Arthas提出了很多建議,其中反映最多的是:

  1. Windows平臺使用者體驗不好
  2. Attach的程式和最終連線的程式不一致
  3. 某些環境下沒有安裝Telnet,不能連線到Arthas Server
  4. 本地啟動,不需要下載遠端(很多公司安全考慮)
  5. 下載速度慢(預設從maven central repository下載)

在Arthas 3.0.5版本里,我們在使用者體驗方面做了很多改進,下面逐一介紹。

全平臺通用的arthas-boot

arthas-boot是新增加的支援全平臺的啟動器,Windows/Mac/Linux下使用體驗一致。下載後,直接java -jar命令啟動:

wget https://alibaba.github.io/arthas/arthas-boot.jar
java -jar arthas-boot.jar
複製程式碼

arthas-boot的功能比以前的as.sh更強大。

  • 比如下載速度比較慢,可以指定阿里雲的映象。

    java -jar arthas-boot.jar --repo-mirror aliyun --use-http
    複製程式碼
  • 比如可以通過session-timeout指定超時時間:

    java -jar arthas-boot.jar --session-timeout 3600
    複製程式碼
  • 更多的功能可以通過java -jar arthas-boot.jar -h檢視

arthas-boot在attach成功之後,會啟動一個java telent client去連線Arthas Server,使用者沒有安裝telnet的情況下也可以正常使用。

優先使用當前目錄的Arthas

在新版本里,預設會從arthas-boot.jaras.sh所在的目錄下查詢arthas home,這樣子使用者全量安裝之後,不需要再從遠端下載Arthas。

  • 使用者可以更方便地整合到自己的基礎映象,或者docker映象裡
  • 對安全要求嚴格的公司,不用再擔心從遠端下載的問題

Attach之前先檢測埠

在之前的版本里,使用者困擾最多的是,明明選擇了程式A,但是實際連線到的卻是程式B。

原因是之前attach了程式B,沒有執行shutdown,下次再執行時,還是連線到程式B。

在新版本里,做了改進:

  • 在attach之前,檢測使用3658埠的程式
  • 在Attach時,如果埠和程式不匹配,會列印出ERROR資訊
$ java -jar arthas-boot.jar
[INFO] Process 1680 already using port 3658
[INFO] Process 1680 already using port 8563
* [1]: 1680 Demo
  [2]: 35542
  [3]: 82334 Demo
3
[ERROR] Target process 82334 is not the process using port 3658, you will connect to an unexpected process.
[ERROR] If you still want to attach target process 82334, Try to set a different telnet port by using --telnet-port argument.
[ERROR] Or try to shutdown the process 1680 using the telnet port first.
複製程式碼

更好的歷史命令匹配功能

  • 新版本對鍵盤Up/Down有了更好的匹配機制,試用有驚喜:)

    比如執行了多次trace,但是在命令列輸入 trace後,想不起來之前trace的具體類名,那麼按Up,可以很輕鬆地匹配到之前的歷史命令,不需要辛苦翻頁。

  • 新版本增加了history命令

改進Web Console的體驗

  • 改進對Windows的字型支援

    之前Windows下面使用的是非等寬字型,看起來很難受。新版本里統一為等寬字型。

  • 增大字型,不再傷害眼睛

arthas-web-console

新增sysenv命令

sysenv命令和sysprop類似,可以列印JVM的環境變數。

新增ognl命令

ognl命令提供了單獨執行ognl指令碼的功能。可以很方便呼叫各種程式碼。

比如執行多行表示式,賦值給臨時變數,返回一個List:

$ ognl '#value1=@System@getProperty("java.home"), #value2=@System@getProperty("java.runtime.name"), {#value1, #value2}'
@ArrayList[
    @String[/opt/java/8.0.181-zulu/jre],
    @String[OpenJDK Runtime Environment],
]
複製程式碼

watch命令列印耗時,更方便定位效能瓶頸

之前watch命令只支援列印入參返回值等,新版本同時列印出呼叫耗時,可以很方便定位效能瓶頸。

$ watch demo.MathGame primeFactors 'params[0]'
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 22 ms.
ts=2018-11-29 17:53:54; [cost=0.131383ms] result=@Integer[-387929024]
ts=2018-11-29 17:53:55; [cost=0.132368ms] result=@Integer[-1318275764]
ts=2018-11-29 17:53:56; [cost=0.496598ms] result=@Integer[76446257]
ts=2018-11-29 17:53:57; [cost=4.9617ms] result=@Integer[1853966253]
複製程式碼

改進類搜尋匹配功能,更好支援lambda和內部類

之前的版本里,在搜尋lambda類時,或者反編繹lambda類有可能會失敗。新版本做了修復。比如

$ jad Test$$Lambda$1/1406718218

ClassLoader:
+-sun.misc.Launcher$AppClassLoader@5c647e05
  +-sun.misc.Launcher$ExtClassLoader@3c1491ce

Location:
/tmp/classes

/*
 * Decompiled with CFR 0_132.
 *
 * Could not load the following classes:
 *  Test
 *  Test$$Lambda$1
 */
import java.lang.invoke.LambdaForm;
import java.util.function.Consumer;

final class Test$$Lambda$1
implements Consumer {
    private Test$$Lambda$1() {
    }

    @LambdaForm.Hidden
    public void accept(Object object) {
        Test.lambda$0((Integer)((Integer)object));
    }
}
複製程式碼

更好的tab自動補全

改進了很多命令的tab自動補全功能,有停頓時,可以多按tab嘗試下。

Release Note

詳細的Release Note:github.com/alibaba/art…

相關文章