日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

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

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

那么,問題來了,如果我們想要一睹該動態生成的代理類內部結構是怎樣的,如何才能便捷做到的?

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

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

根據官網上的介紹,它還可以解決以下問題————

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

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

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

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

線上遇到某個用戶的數據處理有問題,但線上同樣無法 debug,線下無法重現!

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

有什么辦法可以監控到JVM的實時運行狀態?

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

怎樣直接從JVM內查找某個類的實例?

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

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

Alibaba Java診斷工具Arthas查看Dubbo動態代理類

 

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

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")設置成你本地內網的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();
    }

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

}

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

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虛擬機內存里已經存在動態生成的代理類,這時,我們就可以開始通過arthas-boot.jar工具進行查看了。

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

Alibaba Java診斷工具Arthas查看Dubbo動態代理類

 

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

Alibaba Java診斷工具Arthas查看Dubbo動態代理類

 

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

Alibaba Java診斷工具Arthas查看Dubbo動態代理類

 

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

Alibaba Java診斷工具Arthas查看Dubbo動態代理類

 

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

Alibaba Java診斷工具Arthas查看Dubbo動態代理類

 

其中,這里的org.apache.dubbo.common.bytecode.proxy0就是消費者生成的動態代理類,我們可以直接反編譯去查看它內部結構——

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

控制臺就會打印出該動態代理類的內部結構——

/*

 * 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案例當中,當我們執行 String message = service.sayHello("dubbo")去調用遠程接口時,其實是調用了動態代理生成的方法——

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

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

作者:朱季謙

出處:
https://www.cnblogs.com/zhujiqian/p/16114954.html

分享到:
標簽:診斷 工具
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定