Dubbo源码分析:Register注册中心

撸了今年阿里、腾讯和美团的面试,我有一个重要发现…….

作者:backend

出处:https://blog.csdn.net/u010013573/article/category/8462451


Registry

每个注册中心对应一个Registry实例,包括dubbo,zookeeper,redis, multicast。
(1)Set类型的registed:记录provider注册过的service url。
(2)ConcurrentMap<URL, Set> subscribed:consumer订阅URL,URL有变化时的监听器NotifyListener;其中多个NotifyListener是因为consumer存在多个地方调用这个service,NotifyListener的实现为RegistryDirectory。
(3)ConcurrentMap<URL, Map<String, List>> notified:key为消费者url, value为服务提供者url列表。存储消费者consumerURL对应提供者providerURL列表,之后真正进行服务调用的时候,直接从notified列表取出providerURL即可。
(4)file与properties:consumer将从注册中心获取的provider urls保存到本地file,同时加载到properties,避免注册中心挂了,此时consumer还可以连接provider。

RegistryFactory

工厂类,负责生成Registry实例,维护Registry实例缓存,根据底层实现技术的不同,分为dubbo,zookeeper,redis,multicast实现。

RegistryProtocol:注册协议

  1. export方法:负责将provider的service注册到注册中心,具体调用了在ServiceConfig中通过ExtensionLoader加载RegistryProtocol。
  2. 注册中心实现选择:包括:zookeeper,redis,dubbo。确定RegistoryFactory的实现:一旦RegistoryFactory实现确定,则Registry就确定了。
  • 根据ExtensionLoader的分析,通过ServiceConfig确定采用的是RegistryProtocol,通过RegistryProtocol的export方法注册service到注册中心。
  • RegistryProtocol通过ExtensionLoader确定RegistryFactory的实现类。
  1. 具体过程
    (1)在RegistryProtocol的export方法调用了getReigstry(originInvoker):
    201907191002_1.png
    如下:右下角为originInvoker的url的protocol和相关parameters,registry -> zookeeper,所以通过setProtocol设置值为zookeeper,故最终选择的是ZookeeperRegistoryFactory,具体看(2)中RegistryFactory的SPI和@Adaptive规则。
    201907191002_2.png
    getRegistry的实现:模板设计模式,最终由具体实现类实现createRegistry。
    201907191002_3.png
    ZookeeperRegistry的定义:
    201907191002_4.png

(2)RegistryProtocol中registryFactory实现的确定过程
在获取registryProtocol实例时,调用的getAdaptiveExtension的实现,然后底层继续调用createAdaptiveExtension方法。createAdaptiveExtension再调用injectExtension方法,给通过getAdaptiveExtensionClass().newInstance()获取到的RegistryProtocol实例,注入属性值,这个功能类似于spring ioc的实现,RegistryProtocol实例包含setRegistoryFactory方法:
201907191002_5.png
201907191002_6.png
如上图:其中pt为RegistroyFactory,property为registoryFactory,通过objectFactory.getExtension(pt, property)获取到registoryFactory实现类的实例。objectFactory为SpiExtensionFactory的实例,底层调用getExtension:其中type为RegistryFactory。
201907191002_7.png
如下图:RegistoryFactory接口的@SPI注解,value默认为dubbo,表示默认为DubboRegistryFactory
方法getRegistry为使用@Adaptive({“protocol”}),protocol表示调用这个方法的时候,根据URL的protocol对应的值或决定使用哪个RegistryFactory接口实现,由(1)分析protocol为zookeeper。
201907191002_8.png
继续debug源码,查找loader.getAdaptiveExtension()最终获取到哪个RegistryFactory实现。最终进入ExtensionLoader的createAdaptiveExtensionClassCode方法,生成的代码如下:
201907191002_9.png
即:首先根据调用方法getRegistry(URL url),url的protocol选择RegistryFactory,如果protocol为null,则使用defaultExtName,默认为dubbo。而由(1)分析可知:url的protocol为zookeeper,故最终调用的为ZookeeperRegistryFactory。
201907191002_10.png
动态生成的代码如下:

    package com.alibaba.dubbo.registry;
    import com.alibaba.dubbo.common.extension.ExtensionLoader;
    public class RegistryFactory$Adpative implements com.alibaba.dubbo.registry.RegistryFactory {
        public com.alibaba.dubbo.registry.Registry getRegistry(com.alibaba.dubbo.common.URL arg0) {
            if (arg0 == null) throw new IllegalArgumentException("url == null");
            com.alibaba.dubbo.common.URL url = arg0;
            String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );
            if(extName == null)
                throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.registry.RegistryFactory) name from url(" + url.toString() + ") use keys([protocol])");
            com.alibaba.dubbo.registry.RegistryFactory extension = (com.alibaba.dubbo.registry.RegistryFactory)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.registry.RegistryFactory.class).getExtension(extName);
            return extension.getRegistry(arg0);
        }
    }

赞(0) 打赏

如未加特殊说明,此网站文章均为原创,转载必须注明出处。Java 技术驿站 » Dubbo源码分析:Register注册中心
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

关注【Java 技术驿站】公众号,每天早上 8:10 为你推送一篇技术文章

扫描二维码关注我!


关注【Java 技术驿站】公众号 回复 “VIP”,获取 VIP 地址永久关闭弹出窗口

免费获取资源

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏