使用Arthas獲取Spring應用上下文的2種方法


背景

項目中有時我們需要對應用進行診斷和調試,如調用某個接口進行業務驗證、業務執行、數據修復、刷新緩存、查詢數據、跑批量任務等等。

  • 微服務項目
    如基於Dubbo搭建的微服務,我們可使用Dubbo支持的telnet運維管理,其中invoke命令方便直接調用Dubbo接口;
    也可整合swagger-dubbo,方便在網頁界面上直接調用Dubbo接口。

  • web項目
    如使用了SpringMVC、Jersey等框架,可考慮暴露一些運維相關的內部rest api,里面調用業務方法,用於某些場景下人工操作處理。

有些情況下以上條件不具備,如不能修改代碼、希望不修改代碼、不方便修改代碼、沒有源代碼等原因。

Arthas

Arthas 是Alibaba開源的Java診斷工具,可以用於快速診斷Java應用和定位分析問題。
官網:https://arthas.aliyun.com

實戰

項目一般都是基於Spring/SpringBoot來構建,如果我們能獲取spring的ApplicationContext,就能方便獲取spring容器的Bean,然后調用里面的方法。
啟動Arthas:java -jar arthas-boot.jar,選擇應用。

  • 方法1
    通過Dubbo的SpringExtensionFactory來獲取

(1). 先掃描類,-d參數表示獲取詳細信息
sc -d com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory
注意結果里的classLoaderHash值。

(2). 通過ognl命令,-c參數指定ClassLoader的hash值,即上一步的classLoaderHash值。
ognl -c 6b884d57 '@com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory@contexts.iterator.next'
觀察輸出結果,此時已成功獲取到Spring的ApplicationContext,接下來可以根據場景和需要靈活使用了。

例如,調用某service方法:
ognl -c 6b884d57 '#context=@com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory@contexts.iterator.next,#context.getBean("songService").findRandomSongList(5)'

  • 方法2
    通過實現ApplicationContextAware接口來獲取
    (1). 項目中有一個實現了ApplicationContextAware接口的類
    例如:
package com.cdfive.common.util;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * @author cdfive
 */
public class SpringContextUtil implements ApplicationContextAware {

    private static ApplicationContext APPLICATION_CONTEXT;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        APPLICATION_CONTEXT = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
        return APPLICATION_CONTEXT;
    }

    public static <T> T getBean(Class<T> beanType) {
        return getApplicationContext() != null ? getApplicationContext().getBean(beanType) : null;
    }

    public static Object getBean(String beanName) {
        return getApplicationContext() != null ? getApplicationContext().getBean(beanName) : null;
    }
}

(2). 掃描類,-d參數表示獲取詳細信息
sc -d com.xxx.SpringContextUtil

(3). 調用類里獲取ApplicationContext的方法
ognl -c 6b884d57 '@com.cdfive.common.util.SpringContextUtil@getApplicationContext()'
觀察輸出結果,此時已成功獲取到Spring的ApplicationContext,接下來可以根據場景和需要靈活使用了。

例如,調用某service方法:
ognl -c 6b884d57 '#context=@com.cdfive.common.util.SpringContextUtil@getApplicationContext(),#context.getBean("songService").findRandomSongList(5)'

注:方法1需要應用使用了Dubbo框架,方法2則應用范圍更廣,應用使用了Spring框架即可。

思考

通過Arthas,我們可方便的對Java應用進行分析和診斷,對於測試和線上問題分析和定位很有幫助,並且很大提高了效率;
同時也應注意到安全因素,開發、測試環境還好,線上環境由於正在被使用,開發人員直接操作線上接口有一定風險;
操作失誤可能破壞線上數據的完整性,影響系統穩定等等,因此使用上需要有所限制。比如分析線上疑難問題,限制僅調用查詢數據的接口;
當有更新數據的需求時,考慮接口的冪等性、做好數據備份、二次確認等,避免在分析線上問題反而造成新的問題,要有嚴防線上事故的高度警惕。

此外,基於Arthas定制二次開發的系統,或者跟開發IDE結合的插件,可以更好的滿足需求,使用上也會更加高效、安全、智能。
參考業內已有的技術分享:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM