• dubbo源码分析13——服务本地暴露 exportLocal(url)


    dubbo服务的本地暴露,显然是针对当服务消费者和服务提供者都在同一个jvm的进程内这种场景 。通常是发生在服务之间的调用的情况下。一种情况就是A服务调用B服务的情况,如果A服务和B服务都是在一个线程中进行服务暴露的,就是本地调用。  

    下面先看本地暴露的源码:

     private void exportLocal(URL url) {
    //这是本协议url示例:injvm://127.0.0.1/org.huxin.dubbo.test.user.service.UserInterface?anyhost=true&application=dubbo-provider&default.retries=0&default.timeout=5000&dubbo=2.8.4&generic=false&interface=org.huxin.dubbo.test.user.service.UserInterface&methods=getUserById,getUserList,updateUsers&organization=huxin&owner=programmer&pid=5964&retries=0&serialization=kryo&side=provider&timestamp=1513044127040
    if (!Constants.LOCAL_PROTOCOL.equalsIgnoreCase(url.getProtocol())) { URL local = URL.valueOf(url.toFullString()) .setProtocol(Constants.LOCAL_PROTOCOL) .setHost(NetUtils.LOCALHOST) .setPort(0); // ServiceClassHolder是用来保存当前服务接口实例ref对应的Class的,是一个简单的单例实现 ServiceClassHolder.getInstance().pushServiceClass(getServiceClass(ref));        //由于默认protocol是dubbo,所以此处的protocol应是com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol类的实例 Exporter<?> exporter = protocol.export( proxyFactory.getInvoker(ref, (Class) interfaceClass, local)); exporters.add(exporter); logger.info("Export dubbo service " + interfaceClass.getName() +" to local registry"); } }

    根据上面的源码,我们只需搞清楚Invoker实例是如何产生的,Invoker是什么,以及DubboProtocol的export方法就可以分析清楚本地暴露的过程了。
    1. proxyFactory.getInvoker(ref, (Class) interfaceClass, local)
    (1)首先是
    proxyFactory的来历
    ServiceConfig类中初始化时进行实例化:private static final ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
    根据之前对dubbo的SPI机制,这个proxyFactory当是com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory类的实例,也就是使用Javassist技术来产生Invoker对象。
    ProxyFactory接口有两个方法:
    <T> T getProxy(Invoker<T> invoker) throws RpcException; //供消费者使用

                         <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException;  //服务提供者使用

           (2) JavassistProxyFactory实例的 getInvoker方法分析

           可以通过如下源码看出Invoker实例在被调用时实隙地是通过其内部的wrapper对象调用proxy对象来完成的 ,下面分析下这个方法传入的参数:

    •         第一个参数proxy传入是的ref变量  ,

               ref的定义:private T  ref; //接口实现类的引用  ,就是接口实现类的Class的实例 

                赋值的相关代码参见: http://www.cnblogs.com/hzhuxin/p/7677265.html  

    •      第二个参数 type  的定义是:private Class<?>            interfaceClass;  //也就是我们定义服务接口
    •      第三个参数url 比较理解,是由之前面的调用方法 doExportUrlsFor1Protocol(protocolConfig, registryURLs) 方法拼接出来的
    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
            // TODO Wrapper类不能正确处理带$的类名
            final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);
            return new AbstractProxyInvoker<T>(proxy, type, url) {
                @Override
                protected Object doInvoke(T proxy, String methodName, 
                                          Class<?>[] parameterTypes, 
                                          Object[] arguments) throws Throwable {
                    return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
                }
            };
        }
    2. DubboProtocol的export方法分析:
    因本方法比较重要,新开一篇进行分析 ,参见 http://www.cnblogs.com/hzhuxin/p/8228982.html
  • 相关阅读:
    小程序配置安装
    微信小程序--录制音频,播放音频
    微信小程序报错.wxss无法找到
    linux 安装 elasticsearch
    Ubuntu 安装Logstash
    python 开发微信 自定义菜单
    微信 python搭建服务器
    vue 本地存储数据 sessionStorage
    luogu1742 最小圆覆盖
    luogu1501 [国家集训队]Tree II
  • 原文地址:https://www.cnblogs.com/hzhuxin/p/8022783.html
Copyright © 2020-2023  润新知