最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Alibaba?Java診斷工具Arthas查看Dubbo動態(tài)代理類

 更新時間:2022年04月08日 09:10:42   作者:朱季謙  
這篇文章主要介紹了Alibaba?Java診斷工具Arthas查看Dubbo動態(tài)代理類?,它可以幫助我們查看JDK或者javassist生成的動態(tài)代理類,當然,它的功能遠不止此,還可以在生產(chǎn)環(huán)境進行診斷,需要的朋友可以參考下

閱讀Dubbo源碼過程中,會發(fā)現(xiàn),Dubbo消費端在做遠程調(diào)用時,默認通過 Javassist 框架為服務接口生成動態(tài)代理類,調(diào)用javassist框架下的JavassistProxyFactory類的getProxy(Invoker invoker, Class<?>[] interfaces)方法,動態(tài)生成一個存放在JVM中的動態(tài)代理類。

public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
    return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}

那么,問題來了,如果我們想要一睹該動態(tài)生成的代理類內(nèi)部結(jié)構(gòu)是怎樣的,如何才能便捷做到的?

這就是我想介紹的一款工具,它可以幫助我們查看JDK或者javassist生成的動態(tài)代理類,當然,它的功能遠不止此,還可以在生產(chǎn)環(huán)境進行診斷。

Arthas 是Alibaba開源的Java診斷工具,官方在線文檔地址:https://arthas.aliyun.com/doc/

根據(jù)官網(wǎng)上的介紹,它還可以解決以下問題————

當你遇到以下類似問題而束手無策時,Arthas可以幫助你解決:

這個類從哪個 jar 包加載的?為什么會報各種類相關(guān)的 Exception?

我改的代碼為什么沒有執(zhí)行到?難道是我沒 commit?分支搞錯了?

遇到問題無法在線上 debug,難道只能通過加日志再重新發(fā)布嗎?

線上遇到某個用戶的數(shù)據(jù)處理有問題,但線上同樣無法 debug,線下無法重現(xiàn)!

是否有一個全局視角來查看系統(tǒng)的運行狀況?

有什么辦法可以監(jiān)控到JVM的實時運行狀態(tài)?

怎么快速定位應用的熱點,生成火焰圖?

怎樣直接從JVM內(nèi)查找某個類的實例?

這些方案本文暫不展開,這里只展開通過該工具查看Dubbo生成的動態(tài)代理類。

我是直接在使用dubbo-parent源碼中的例子,分別啟動了提供者與消費者。

首先,啟動提供者方法——

public class Application {
    public static void main(String[] args) throws Exception {
            startWithBootstrap();   
    }
    private static boolean isClassic(String[] args) {
        return args.length > 0 && "classic".equalsIgnoreCase(args[0]);
    }
    private static void startWithBootstrap() {
        ServiceConfig<DemoServiceImpl> service = new ServiceConfig<>();
        service.setInterface(DemoService.class);
        service.setRef(new DemoServiceImpl());
        DubboBootstrap bootstrap = DubboBootstrap.getInstance();
        RegistryConfig registryConfig = new RegistryConfig("zookeeper://127.0.0.1:2181");
        registryConfig.setTimeout(20000);
        ProtocolConfig protocolConfig = new ProtocolConfig();
        protocolConfig.setName("dubbo");
        protocolConfig.setHost("192.168.100.1");
        protocolConfig.setPort(20877);
        bootstrap.application(new ApplicationConfig("dubbo-demo-api-provider"))
                .registry(registryConfig)
                .service(service)
                .protocol(protocolConfig)
                .start()
                .await();
    }
}

注意,需要配置RegistryConfig自己的zookeeper, protocolConfig.setHost("xxx.xxx.xxx.xxx")設(shè)置成你本地內(nèi)網(wǎng)的ip即可;

DemoServiceImpl類詳情——

public class DemoServiceImpl implements DemoService {
    private static final Logger logger = LoggerFactory.getLogger(DemoServiceImpl.class);

    @Override
    public String sayHello(String name) {
        logger.info("Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
        return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress();
    }

    public CompletableFuture<String> sayHelloAsync(String name) {
        return null;

}

接著,啟動消費者,這里可以設(shè)置一個休眠時間,這樣就可以一直維持消費者運行在內(nèi)存當中——

public class Application {
    public static void main(String[] args) {
            runWithRefer();
    }
    private static void runWithRefer() {
        RegistryConfig registryConfig = new RegistryConfig("zookeeper://127.0.0.1:2181");
        registryConfig.setTimeout(30000);
        ProtocolConfig protocolConfig = new ProtocolConfig();
        protocolConfig.setName("dubbo");
        protocolConfig.setHost("192.168.200.1");
        protocolConfig.setPort(20899);
        ReferenceConfig<DemoService> reference = new ReferenceConfig<>();
        reference.setApplication(new ApplicationConfig("dubbo-demo-api-consumer"));
        reference.setRegistry(registryConfig);
        reference.setInterface(DemoService.class);
        DemoService service = reference.get();
        String message = service.sayHello("dubbo");
        System.out.println("打印了5555555"+message);
        try {
            Thread.sleep(100000000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
}

當Dubbo的服務提供者與消費者都正常運行時,說明此時JVM虛擬機內(nèi)存里已經(jīng)存在動態(tài)生成的代理類,這時,我們就可以開始通過arthas-boot.jar工具進行查看了。

首先,將arthas-boot.jar工具下載到你本地,我的是Windows,隨便放到一個目錄當中,例如——

接著,直接在運行著Dubbo消費端進程的IDEA上打開Terminal——

然后,輸入 java -jar C:\Users\92493\Downloads\12229238_g\arthas-boot.jar ,arthas正常運行成功話,將列出當前JVM上運行的進程——

可以看到我們剛剛啟動的provider進程與consumer進程,這時,只需要輸入對應進程前面的編號【5】,就可以將Arthas 關(guān)聯(lián)到啟動類為 org.apache.dubbo.demo.consumer.Application的 Java 進程上了——

到這一步,我們就可以通過指令 sc *.proxy *模糊查詢帶有proxy標志的類名了,動態(tài)代理生成的類一般都是以Proxy標志——

其中,這里的org.apache.dubbo.common.bytecode.proxy0就是消費者生成的動態(tài)代理類,我們可以直接反編譯去查看它內(nèi)部結(jié)構(gòu)——

[arthas@57676]$ jad org.apache.dubbo.common.bytecode.proxy0

控制臺就會打印出該動態(tài)代理類的內(nèi)部結(jié)構(gòu)——

/*
 * Decompiled with CFR.
 * 
 * Could not load the following classes:
 * com.alibaba.dubbo.rpc.service.EchoService
 * org.apache.dubbo.common.bytecode.ClassGenerator$DC
 * org.apache.dubbo.demo.DemoService
 * org.apache.dubbo.rpc.service.Destroyable
   */
   package org.apache.dubbo.common.bytecode;
import com.alibaba.dubbo.rpc.service.EchoService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.concurrent.CompletableFuture;
import org.apache.dubbo.common.bytecode.ClassGenerator;
import org.apache.dubbo.demo.DemoService;
import org.apache.dubbo.rpc.service.Destroyable;
public class proxy0 implements ClassGenerator.DC,Destroyable,EchoService,DemoService {
public static Method[] methods;
private InvocationHandler handler;
public String sayHello(String string) {
    Object[] objectArray = new Object[]{string};
    Object object = this.handler.invoke(this, methods[0], objectArray);
    return (String)object;
}
public CompletableFuture sayHelloAsync(String string) {
    Object[] objectArray = new Object[]{string};
    Object object = this.handler.invoke(this, methods[1], objectArray);
    return (CompletableFuture)object;
}
public Object $echo(Object object) {
    Object[] objectArray = new Object[]{object};
    Object object2 = this.handler.invoke(this, methods[2], objectArray);
    return object2;
}
public void $destroy() {
    Object[] objectArray = new Object[]{};
    Object object = this.handler.invoke(this, methods[3], objectArray);
}
public proxy0() {
}
public proxy0(InvocationHandler invocationHandler) {
    this.handler = invocationHandler;
  }
}

在Dubbo案例當中,當我們執(zhí)行 String message = service.sayHello("dubbo")去調(diào)用遠程接口時,其實是調(diào)用了動態(tài)代理生成的方法——

public String sayHello(String string) {
    Object[] objectArray = new Object[]{string};
    Object object = this.handler.invoke(this, methods[0], objectArray);
    return (String)object;
}

舉一反三,這個Arthas工具類可以在線上生產(chǎn)環(huán)境查看一些我們新部署的代碼,看是否是新改動的。

到此這篇關(guān)于Alibaba Java診斷工具Arthas查看Dubbo動態(tài)代理類的文章就介紹到這了,更多相關(guān)Alibaba Java診斷工具Arthas內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java必備知識之位運算及常見進制解讀

    Java必備知識之位運算及常見進制解讀

    從現(xiàn)代計算機中所有的數(shù)據(jù)二進制的形式存儲在設(shè)備中。即 0、1 兩種狀態(tài),計算機對二進制數(shù)據(jù)進行的運算(+、-、*、/)都是叫位運算,即將符號位共同參與運算的運算
    2021-10-10
  • Java中使用BigDecimal進行浮點數(shù)運算

    Java中使用BigDecimal進行浮點數(shù)運算

    這篇文章主要介紹了Java中使用BigDecimal進行浮點數(shù)運算,需要的朋友可以參考下
    2014-07-07
  • Java程序結(jié)構(gòu)與常量變量難點解析

    Java程序結(jié)構(gòu)與常量變量難點解析

    JAVA的基本結(jié)構(gòu)就是順序結(jié)構(gòu),除非特別指明,否則就按照順序一句一句執(zhí)行順序結(jié)構(gòu)是最簡單的算法結(jié)構(gòu),語句與語句之間,框與框之間是按從上到下的順序進行的,它是由若干個依次執(zhí)行的處理步驟組成的,它是任何一個算法都離不開的一種基本算法結(jié)構(gòu)
    2021-10-10
  • SpringBoot實現(xiàn)Server-Sent Events(SSE)的使用完整指南

    SpringBoot實現(xiàn)Server-Sent Events(SSE)的使用完整指南

    使用SpringBoot實現(xiàn)Server-Sent Events(SSE)可以有效處理實時數(shù)據(jù)推送需求,具有單向通信、輕量級和高實時性等優(yōu)勢,本文詳細介紹了在SpringBoot中創(chuàng)建SSE端點的步驟,并通過代碼示例展示了客戶端如何接收數(shù)據(jù),適用于實時通知、數(shù)據(jù)展示和在線聊天等場景
    2024-09-09
  • Java 集合實現(xiàn)分頁的方法(業(yè)務代碼實現(xiàn)分頁)

    Java 集合實現(xiàn)分頁的方法(業(yè)務代碼實現(xiàn)分頁)

    在Java開發(fā)中,有些場景比較復雜,受限制,不好在sql查詢層面實現(xiàn)分頁,需要在查詢的list結(jié)果后,將list分頁返回,如何實現(xiàn)呢,帶著這個問題一起通過本文學習吧
    2025-02-02
  • Java中CompletableFuture?的詳細介紹

    Java中CompletableFuture?的詳細介紹

    這篇文章主要介紹了Java中的CompletableFuture,通過創(chuàng)建?CompletableFuture?的對象的工廠方法展開詳細的內(nèi)容介紹,需要的小伙伴可以參考一下
    2022-05-05
  • 淺談java中對集合對象list的幾種循環(huán)訪問

    淺談java中對集合對象list的幾種循環(huán)訪問

    下面小編就為大家?guī)硪黄猨ava中對集合對象list的幾種循環(huán)訪問詳解。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-07-07
  • Java獲取字符串編碼格式實現(xiàn)思路

    Java獲取字符串編碼格式實現(xiàn)思路

    文件編碼的格式?jīng)Q定了文件可存儲的字符類型,所以得到文件的類型至關(guān)重要,下文筆者講述獲取一個文本文件的格式信息的方法分享及java字符串編碼格式實現(xiàn),感興趣的朋友一起看看吧
    2022-09-09
  • Spring Boot application.yml配置文件示例詳解

    Spring Boot application.yml配置文件示例詳解

    本文詳細介紹了SpringBootapplication.yml配置文件的使用和配置項,通過學習本文,您應該已經(jīng)掌握了如何使用application.yml文件來配置SpringBoot應用程序的不同組件,如數(shù)據(jù)源、數(shù)據(jù)庫、緩存、郵件服務等,感興趣的朋友一起看看吧
    2025-02-02
  • Mybatis的update更新批量與普通解決方式對比

    Mybatis的update更新批量與普通解決方式對比

    這篇文章主要為大家介紹了Mybatis的update更新批量與普通解決方式對比,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-04-04

最新評論

吴忠市| 榆社县| 广水市| 奇台县| 名山县| 北川| 阿拉善右旗| 福建省| 昆山市| 诸城市| 新巴尔虎右旗| 增城市| 兰溪市| 和林格尔县| 嵊州市| 灵武市| 衡阳县| 林甸县| 五原县| 永昌县| 金平| 麻栗坡县| 蓝田县| 邢台县| 襄城县| 西藏| 钟祥市| 平定县| 大竹县| 吉安市| 太仓市| 三亚市| 阳西县| 武穴市| 宝鸡市| 滨海县| 炎陵县| 银川市| 鄂伦春自治旗| 沙坪坝区| 麻阳|