阿里開源那個牛逼帶閃電的問題排查工具居然不會用?最佳實踐來了

入門步驟

安裝

https://arthas.gitee.io/install-detail.htmlhtml

上述命令會下載啓動腳本文件 as.sh 到當前目錄,執行方式:java

curl -L https://alibaba.github.io/arthas/install.sh | sh

as.sh 啓動 :nginx

curl -sk https://arthas.gitee.io/arthas-boot.jar -o ~/.arthas-boot.jar  && echo "alias as.sh='java -jar ~/.arthas-boot.jar --repo-mirror aliyun --use-http'" >> ~/.bashrc && source ~/.bashrc

在線教程體驗

https://alibaba.github.io/arthas/arthas-tutorials?language=cngit

固然也能夠本身本地體驗一下~本身經過下載一個 arthas-idea-plugin的體驗demo 直接本地上手github

https://github.com/WangJi92/arthas-plugin-demoweb

全局命令說明:spring

-x 是展現結果屬性遍歷深度,默認爲 1express

-n 是執行的次數 ,q 退出性能優化

-c classloader 的hash值bash

退出 q ,關閉 stop

瞭解最經常使用的trace、watch的功能

watch和trace 是arthas 診斷中對於開發人員解決線上的問題最經常使用的功能!

trace

基本示例:

trace com.wangji92.arthas.plugin.demo.controller.CommonController getRandomInteger -n 5 '1==1'

https://arthas.gitee.io/trace.html

  • 性能優化~

  • 調用的這個方法,走的具體流程是咋樣的!能夠經過調用鏈看出來。

  • 有異常了能夠查看異常的堆棧

高級的功能:

trace命令只會trace匹配到的函數裏的子調用,並不會向下trace多層。由於trace是代價比較貴的,多層trace可能會致使最終要trace的類和函數很是多。

示例:

trace -E xxxClassA|xxxClassB method1 | method2

如:

trace -E com.wangji92.arthas.plugin.demo.controller.CommonController|com.wangji92.arthas.plugin.demo.service.ArthasTestService traceE|doTraceE -n 5 '1==1'

watch

https://arthas.gitee.io/watch.html

wathc 從字面上理解就是觀察值的信息,能夠查看入參、返回值、異常、能夠執行表達式獲取靜態變量、target.xxx調用目標實施的字段、方法等等都行~只要你想獲得沒有作不到的~

基本示例:

watch com.wangji92.arthas.plugin.demo.controller.CommonController traceE '{params,returnObj,throwExp}' -n 5 -x 3 '1==1'

arthas 表達式核心變量

public class Advice {



    private final ClassLoader loader;

    private final Class<?> clazz;

    private final ArthasMethod method;

    private final Object target;

    private final Object[] params;

    private final Object returnObj;

    private final Throwable throwExp;

    private final boolean isBefore;

    private final boolean isThrow;

    private final boolean isReturn;



    // getter/setter  

}  

從watch 和 trace 中看到 後面的 '1==1' 執行的是一個條件表達式 當值爲true 的時候經過執行了一個ognl 表達式 ,watch 觀察 params,returnObj,throwExp 入參、返回值、是否異常 這個也是一個表達式,那麼這個究竟是咋回事?

spring el 表達式

沒有學習過ognl 使用多年的spring 必定知道它的el 表達式,el 表達式中也有一種概念叫作【Context 上下文,和表達式】 以下所示,由於有了simple這個上下文 才能解析 "booleanList[0]" 這個腳本的含義~ 這個很熟悉,很好理解,那麼ognl 表達式同樣不難了。

class Simple {

    public List<Boolean> booleanList = new ArrayList<Boolean>();

}



Simple simple = new Simple();



simple.booleanList.add(true);



StandardEvaluationContext simpleContext = new StandardEvaluationContext(simple);



// false is passed in here as a string. SpEL and the conversion service will

// correctly recognize that it needs to be a Boolean and convert it

parser.parseExpression("booleanList[0]").setValue(simpleContext, "false");



// b will be false

Boolean b = simple.booleanList.get(0);

ognl 表達式

arthas 也是同樣的,只是使用了一個叫作ognl的腳本,核心變量就是他的上下文,能夠直接獲取到這些字段。watch 觀察的這幾個字段 params,returnObj,throwExp 也就是咱們所謂的上下文的概念,觀察參數、返回值、和異常的信息。

以下是arthas 源碼中 表達式評估和watch 觀察值執行的代碼!Advice 就是一個上下文,這裏還增長了一個變量 const。知道了這些那不是很簡單??

com.taobao.arthas.core.advisor.ReflectAdviceListenerAdapter#isConditionMet

/**

 * 判斷條件是否知足,知足的狀況下須要輸出結果

 * @param conditionExpress 條件表達式

 * @param advice 當前的advice對象

 * @param cost 本次執行的耗時

 * @return true 若是條件表達式知足

 */

protected boolean isConditionMet(String conditionExpress, Advice advice, double cost) throws ExpressException {

    return StringUtils.isEmpty(conditionExpress) ||

            ExpressFactory.threadLocalExpress(advice).bind(Constants.COST_VARIABLE, cost).is(conditionExpress);

}



protected Object getExpressionResult(String express, Advice advice, double cost) throws ExpressException {

    return ExpressFactory.threadLocalExpress(advice)

            .bind(Constants.COST_VARIABLE, cost).get(express);

}

表達式實踐

arthas 羣常常有人問重載方法如何判斷,無非就是評估條件?參數的個數、第一個參數是什麼?返回值的類型等等均可以做爲你評估的條件。以下的watch 前面的一段是觀察的值、後面這一段是表達式評估 ,知足了條件才執行。

入口長度大於0:

watch com.wangji92.arthas.plugin.demo.controller.CommonController traceE '{params,returnObj,throwExp}' -n 5 -x 3 'params.length >0'

返回值爲String 且長度大於5:

watch com.wangji92.arthas.plugin.demo.controller.CommonController traceE '{params,returnObj,throwExp}' -n 5 -x 3 'returnObj instanceof java.lang.String && returnObj.length>5'

條件表達式+異步任務

只有特定的場景纔會有bug ,如何排查bug?

一天只出現一兩次如何解決?

條件表達式主要是用來過濾使用,好比某些場景只是在特定的參數纔會出現,可能會花費不少的時間去等待,這個時候可使用條件表達式過濾 +異步任務

ognl 表達式

https://arthas.gitee.io/ognl.html

從上面看,ognl 在watch、trace上面無所不能啊,其實還有tt 也是 使用ognl 表達式執行邏輯的. @xxxClas@xxxStaticField 是靜態變量的語法糖 ognl的,好好看一下官方的文檔。

OGNL特殊用法請參考:https://github.com/alibaba/arthas/issues/71

獲取靜態變量

靜態變量因爲 一個jvm 中可能被多個classloader加載,jvm 認定爲一個實例是一個classloader加載哦,因此須要知道當前靜態類的hash 值(sc -d com.wangji92.arthas.plugin.demo.controller.StaticTest)能夠經過這個命令獲取。

ognl  -x  3 '@com.wangji92.arthas.plugin.demo.controller.StaticTest@INVOKE_STATIC_DOUBLE' -c e374b99

調用spring 方法?

watch 執行ognl 語法中獲取spring context 而後進行調用bean的方法

watch -x 3 -n 1  org.springframework.web.servlet.DispatcherServlet doDispatch '@org.springframework.web.context.support.WebApplicationContextUtils@getWebApplicationContext(params[0].getServletContext()).getBean("commonController").getRandomInteger()'

ognl 執行靜態的一個spring context 而後調用bean 的方法

ognl -x 3 '#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#springContext.getBean("commonController").getRandomInteger()' -c e374b99

有沒有起飛的感受,無所不能!前提是你要掌握一些ognl的一些簡單的語法!

完畢

對於線上排查問題,我感受這幾個命令夠你用了,還有一些其餘的反編譯、火焰圖、.. 時間隧道、logger 等級修改,jvm環境信息等等感受是有頻率都沒有上面的高,畢竟jvm信息有專門的監控~即便沒有arthas 你也能夠找到更好的工具去分析堆棧,jvm故障。

一些特殊的用戶案例值得學習思考: https://github.com/alibaba/arthas/issues?q=label%3Auser-case

完了?

啊?這麼多命令 記不住啊 還有一些高級的ognl的語法涼了… 讓你獲取一下全部的spring的環境變量咋辦?trace、watch 這兩個命令我尚未體驗夠呢?更加高級的讓我如何是好啊!好了,請看下文。

進階

前提

前提是你對於arthas 有了大概的理解,基本上的命令都有點概念了,ognl 簡單的語法可以看懂了.. 簡單的條件表達式會用了。以前咱們說過arthas的命令這麼多 要記住小本本少不了啊!難受想哭~ 不要急,汪小哥來給你解決問題。

目前Arthas 官方的工具還不夠足夠的簡單,須要記住一些命令,特別是一些擴展性特別強的高級語法,好比ognl獲取spring context 隨心所欲,watch、trace 不夠簡單,須要構造一些命令工具的信息,所以只須要一個可以簡單處理字符串信息的插件便可使用。當在處理線上問題的時候須要最快速、最便捷的命令,所以arthas idea 插件仍是有存在的意義和價值的。

arthas idea plugin

這個插件的意義不是處理協議層面的問題,主要解決命令生成的問題,因爲工程在idea 裏面管理,你想一想你要watch 哪一個類,這個插件是知道的,幫助你更方便、更加快捷的構建命令。使用arthas idea 插件 這一點必定要理解哦!主要解決你如何構造命令的問題

阿里開源那個牛逼帶閃電的問題排查工具居然不會用?最佳實踐來了


解決的問題

spring 環境變量優先級問題 獲取靜態變量 火焰圖集成 logger 命令集成 反編譯集成 trace -E 集成 tt 集成 ……. 基本上你可以在arths 上面看到的功能都集成到了這個上面!直接在idea 裏面搜索arths idea 便可安裝。

經常使用特殊用法問題

靜態變量

能夠直接獲取 ognl 獲取

ognl  -x  3 '@com.wangji92.arthas.plugin.demo.controller.StaticTest@INVOKE_STATIC_DOUBLE' -c e374b99

能夠經過watch 獲取 (光標放置在字段上)

watch com.wangji92.arthas.plugin.demo.controller.StaticTest * '{params,returnObj,throwExp,@com.wangji92.arthas.plugin.demo.controller.StaticTest@INVOKE_STATIC_DOUBLE}' -n 5 -x 3 '1==1'

通常的變量

能夠經過spring context.getBean().field 獲取(這個是要配置一個靜態的spring context 看使用文檔) tt 、watch 也是能夠的哦~ 同樣的原理

ognl -x 3 '#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#springContext.getBean("staticTest").filedValue' -c e374b99

watch 獲取 放置在字段上便可

watch com.wangji92.arthas.plugin.demo.controller.StaticTest * '{params,returnObj,throwExp,target.filedValue}' -n 5 -x 3 'method.initMethod(),method.constructor!=null || !@java.lang.reflect.Modifier@isStatic(method.method.getModifiers())'

選擇的配置項的值 springContext.getEnvironment() (這個是要配置一個靜態的spring context 看使用文檔)

ognl -x 3 '#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#springContext.getEnvironment().getProperty("custom.name")' -c e374b99

獲取全部的配置項的值 watch 獲取spring context tt 、static 也是能夠的哦~ 同樣的原理

watch -x 3 -n 1  org.springframework.web.servlet.DispatcherServlet doDispatch '#springContext=@org
相關文章
相關標籤/搜索