欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

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

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

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

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

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

當(dāng)你遇到以下類似問題而束手無策時(shí),Arthas可以幫助你解決:

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

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

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

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

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

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

怎么快速定位應(yīng)用的熱點(diǎn),生成火焰圖?

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

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

我是直接在使用dubbo-parent源碼中的例子,分別啟動(dòng)了提供者與消費(fèi)者。

首先,啟動(dòng)提供者方法——

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;

}

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

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();
        }
}

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

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

接著,直接在運(yùn)行著Dubbo消費(fèi)端進(jìn)程的IDEA上打開Terminal——

然后,輸入 java -jar C:\Users\92493\Downloads\12229238_g\arthas-boot.jar ,arthas正常運(yùn)行成功話,將列出當(dāng)前JVM上運(yùn)行的進(jìn)程——

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

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

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

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

控制臺就會打印出該動(dòng)態(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案例當(dāng)中,當(dāng)我們執(zhí)行 String message = service.sayHello("dubbo")去調(diào)用遠(yuǎn)程接口時(shí),其實(shí)是調(diào)用了動(dòng)態(tài)代理生成的方法——

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

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

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

相關(guān)文章

  • java中常見XML解析器的使用詳解(JAXP,DOM4J,Jsoup,JsoupXPath)

    java中常見XML解析器的使用詳解(JAXP,DOM4J,Jsoup,JsoupXPath)

    為了處理和操作XML數(shù)據(jù),我們需要使用XML解析器,本文將介紹幾種常用的XML解析器,包括JAXP、DOM4J、Jsoup和JsoupXPath,需要的小伙伴可以參考一下
    2023-11-11
  • Java多線程基礎(chǔ)

    Java多線程基礎(chǔ)

    這篇文章主要介紹Java多線程基礎(chǔ),線程是進(jìn)程的一個(gè)實(shí)體,是CPU調(diào)度和分派的基本單位,它是比進(jìn)程更小的能獨(dú)立運(yùn)行的基本單位,多線程指在單個(gè)程序中可以同時(shí)運(yùn)行多個(gè)不同的線程執(zhí)行不同的任務(wù),下面來學(xué)習(xí)具體的詳細(xì)內(nèi)容
    2021-10-10
  • springboot中使用ConstraintValidatorContext驗(yàn)證兩個(gè)字段內(nèi)容相同

    springboot中使用ConstraintValidatorContext驗(yàn)證兩個(gè)字段內(nèi)容相同

    開發(fā)修改密碼功能時(shí),通過ConstraintValidator校驗(yàn)新密碼和確認(rèn)新密碼的一致性,首先定義Matches注解和DTO對象,然后創(chuàng)建MatchesValidator類實(shí)現(xiàn)驗(yàn)證邏輯,對springboot驗(yàn)證字段內(nèi)容相同問題感興趣的朋友一起看看吧
    2024-10-10
  • 如何使用IDEA新建一個(gè)普通的Javaweb項(xiàng)目

    如何使用IDEA新建一個(gè)普通的Javaweb項(xiàng)目

    今天給大家普及如何使用IDEA新建一個(gè)普通的Javaweb項(xiàng)目及配置tomcat的方法,在文末給大家提到如果不想每次都重啟tomcat,可以設(shè)置快捷方式,對idea新建Javaweb項(xiàng)目感興趣的朋友一起看看吧
    2021-06-06
  • Java?事務(wù)注解@Transactional回滾(try?catch、嵌套)問題

    Java?事務(wù)注解@Transactional回滾(try?catch、嵌套)問題

    這篇文章主要介紹了Java?@Transactional回滾(try?catch、嵌套)問題,Spring?事務(wù)注解?@Transactional?本來可以保證原子性,如果事務(wù)內(nèi)有報(bào)錯(cuò)的話,整個(gè)事務(wù)可以保證回滾,但是加上try?catch或者事務(wù)嵌套,可能會導(dǎo)致事務(wù)回滾失敗
    2022-08-08
  • WebUploader客戶端批量上傳圖片 后臺使用springMVC

    WebUploader客戶端批量上傳圖片 后臺使用springMVC

    這篇文章主要為大家詳細(xì)介紹了WebUploader客戶端批量上傳圖片,后臺使用springMVC接收實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-09-09
  • Java橋接模式實(shí)例詳解【簡單版與升級版】

    Java橋接模式實(shí)例詳解【簡單版與升級版】

    這篇文章主要介紹了Java橋接模式,結(jié)合實(shí)例形式分析了java橋接模式簡單版與升級版兩種實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2019-07-07
  • spring boot打jar包發(fā)布的方法

    spring boot打jar包發(fā)布的方法

    這篇文章主要介紹了spring boot打jar包發(fā)布的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-06-06
  • 基于Springboot吞吐量優(yōu)化解決方案

    基于Springboot吞吐量優(yōu)化解決方案

    這篇文章主要介紹了基于Springboot吞吐量優(yōu)化解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • SpringBoot中使用Servlet三大組件的方法(Servlet、Filter、Listener)

    SpringBoot中使用Servlet三大組件的方法(Servlet、Filter、Listener)

    這篇文章主要介紹了SpringBoot中使用Servlet三大組件的方法(Servlet、Filter、Listener),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01

最新評論