dubbo源码二:dubbo服务注册过程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhuqiuhui/article/details/83866453

流程同dubbo服务暴露过程类似,这里只挑出服务注册过程,因为在 dubbo 服务暴露过程中并没有看到服务注册,这里详细分析一下。
工程中的配置文件如下:

<!--定义了提供方应用信息,用于计算依赖关系;在 dubbo-admin 或 dubbo-monitor 会显示这个名字,方便辨识-->
<dubbo:application name="debbo-provider" owner="programmer" organization="dubbox"/>
<!--使用 zookeeper 注册中心暴露服务,注意要先开启 zookeeper-->
<dubbo:registry address="zookeeper://localhost:2181"/>
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" />
<!--使用 dubbo 协议实现定义好的 api.PermissionService 接口-->
<dubbo:service interface="service.DemoService" ref="demoService" protocol="dubbo" />
<!--具体实现该接口的 bean-->
<bean id="demoService" class="Impl.DemoServiceImpl"/>

还是从 ServiceConfig 类中的 doExportUrls说起,如下:
Debug-1:
在这里插入图片描述
Debug-2:
在这里插入图片描述
Debug-3:
在这里插入图片描述
checkRegistry 函数的作用是对 registries 属性进行检验,若为空(没有配置dubbo:registry...),则尝试从配置文件(如properties)读取key是“dubbo.registry.address”的值并构造RegistryConfig,同时放到 registries 属性中。若从配置文件中还没有读取到,则抛出异常。紧接着对 registries 属性中的 RegistryConfig 属性构造。
回到Debug-2,这里主要是构造URL
在这里插入图片描述
构造完URL,在Debug-1中会返回给registryURLs,变量值如下:
在这里插入图片描述
URL没有截全,完整如下:

registry://localhost:2181/com.alibaba.dubbo.registry.RegistryService?application=debbo-provider&dubbo=2.0.2&organization=dubbox&owner=programmer&pid=27589®istry=zookeeper×tamp=1541600447325

接着往下走:
Debug-4:
在这里插入图片描述
Debug-5:
doExportUrlsFor1Protocol 在暴露服务中已经分析过了,这里只分析其中的重点部分:
在这里插入图片描述
其中 wrapperInvoker 变量如下:
在这里插入图片描述
且 Debug-5 中的 protocol 对象是 Protocol接口类的适配类(已经分析过),其适配类源码如下:

package com.alibaba.dubbo.rpc;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class Protocol$Adaptive implements com.alibaba.dubbo.rpc.Protocol {
    
    //…….
    
    public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.RpcException {

        if (arg0 == null) 
            throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null”);

        if (arg0.getUrl() == null) 
            throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null”);

        com.alibaba.dubbo.common.URL url = arg0.getUrl(); 
        String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );

        if(extName == null) 
            throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol]));

        com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
        return extension.export(arg0);
    }
}

根据源码来看,arg0值是wrapperInvoker,extName值是”registry”,就会调用

com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);

其中 ExtensionLoader.getExtensionLoader(Protocol.class) 的 loader 返回值如下:
在这里插入图片描述
接着会调用

ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(”registry”);

Debug-6:
在这里插入图片描述
Debug-7:
在这里插入图片描述
Debug-8:
在这里插入图片描述
Debug-8 返回上述 loader 变量中的 cachedClasses 缓存值,
接着Debug-7走,如下面 cachedWrapperClasses 中变量依次是:ProtocolListenerWrapper、QosProtocolWrapper、ProtocolFilterWrapper
在这里插入图片描述
对三个wrapper依次进行实例化,并返回最后一个实例(ProtocolFilterWrapper),在实例化 wrapper 的时候,可以看到上一个 wrapper 实例被作为下一个 wrapper 实例化时构造函数的入参,于是我们得到 ProtocolFilterWrapper 实例拥有 QosProtocolWrapper 实例,QosProtocolWrapper 实例拥有 ProtocolListenerWrapper 实例,而 ProtocolListenerWrapper 实例拥有 RegistryProtocol 实例。即 ProtocolFilterWrapper -> QosProtocolWrapper -> ProtocolListenerWrapper -> RegistryProtocol,这一点在调用的时候很关键。
在这里插入图片描述
在这里插入图片描述
回到 Debug-6,走完了ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(”registry”) ,即获取了实现Protocol接口,名为“registry”的扩展类实例,即 ProtocolFilterWrapper 实例。

接着看Protocol接口类的适配类源码,最后会执行如下,即进入到 ProtocolFilterWrapper 实例执行 export 方法。

extension.export(arg0);

根据上面的分析,会依次调用 ProtocolFilterWrapper -> QosProtocolWrapper -> ProtocolListenerWrapper -> RegistryProtocol,这里直接看RegistryProtocol 的 export 方法
Debug-9:
在这里插入图片描述
Debug-10:服务暴露过程
在这里插入图片描述
这里是服务暴露过程,这次的url值是:

dubbo://172.17.13.52:20880/service.DemoService?anyhost=true&application=debbo-provider&dubbo=2.5.0&interface=service.DemoService&methods=getPermission&organization=dubbox&owner=programmer&pid=38530&side=provider×tamp=1541669779924

同 registry的调用链路原理一样,只不过这次的调用链路是 ProtocolFilterWrapper -> ProtocolListenerWrapper -> DubboProtocol ,其内部是服务暴露过程,不再分析(可以参考:https://blog.csdn.net/zhuqiuhui/article/details/83689385)。

接着 Debug-9 往下走,就是要找的dubbo服务注册过程!这里给出简要注释,不再详细分析:

//具体的协议去暴露服务
final ExporterChangeableWrapper<T> exporter = doLocalExport(originInvoker);

//得到具体的注册中心,连接注册中心,此时提供者作为消费者引用注册中心核心服务RegistryService
final Registry registry = getRegistry(originInvoker);

//获取要注册到注册中心的url
final URL registedProviderUrl = getRegistedProviderUrl(originInvoker);
        
//调用远端注册中心的register方法进行服务注册,若有消费者订阅此服务,则推送消息让消费者引用此服务
registry.register(registedProviderUrl);
        
//提供者向注册中心订阅所有注册服务的覆盖配置
registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener);
        
//返回暴露后的Exporter给上层ServiceConfig进行缓存
return new Exporter<T>() {。。。}

参考:https://juejin.im/post/5af322c5518825670c45eed8

我的修行之路,欢迎讨论!
微信:bboyzqh
邮箱:[email protected]

猜你喜欢

转载自blog.csdn.net/zhuqiuhui/article/details/83866453