深度解析dubbo服务远程暴露(三)

上篇《深度解析dubbo服务远程暴露(二)》我们讲了DubboProtocol一步步到服务器启动的。但是这些只是我们在服务远程暴露的第一篇的RegistryProtocol#export()方法的第一行,只是介绍了服务器启动,我们知道服务暴露其实是服务器启动+服务注册,今天我们就接着看看RegistryProtocol#export()方法后面的部分。

1.RegistryProtocol#export

 //export invoker  暴露服务    doLocalExport表示本地启动服务不包括去注册中心注册
        final ExporterChangeableWrapper<T> exporter = doLocalExport(originInvoker);
        // 获得注册中心URL
        URL registryUrl = getRegistryUrl(originInvoker);

        //registry provider   获得注册中心对象
        final Registry registry = getRegistry(originInvoker);

        // 获得服务提供者URL
        final URL registeredProviderUrl = getRegisteredProviderUrl(originInvoker);

        //to judge to delay publish whether or not
        boolean register = registeredProviderUrl.getParameter("register", true);
        // 向本地服务注册表注册服务
        ProviderConsumerRegTable.registerProvider(originInvoker, registryUrl, registeredProviderUrl);

        if (register) {  // 向注册中心注册自己
            register(registryUrl, registeredProviderUrl);
            ProviderConsumerRegTable.getProviderWrapper(originInvoker).setReg(true);  // 设置注册标志
        }

        // Subscribe the override data
        // FIXME When the provider subscribes, it will affect the scene : a certain JVM exposes the service and call the same service. Because the subscribed is cached key with the name of the service, it causes the subscription information to cover.
        final URL overrideSubscribeUrl = getSubscribedOverrideUrl(registeredProviderUrl);
        final OverrideListener overrideSubscribeListener = new OverrideListener(overrideSubscribeUrl, originInvoker);
        overrideListeners.put(overrideSubscribeUrl, overrideSubscribeListener);
        registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener);
        //Ensure that a new exporter instance is returned every time export
        return new DestroyableExporter<T>(exporter, originInvoker, overrideSubscribeUrl, registeredProviderUrl);

第一行我们已经讲解过了,然后接着就是从originInvoker里面获取registryUrl,接着就是获取Registry的对象。我们看下这个getRegistry()方法

private Registry getRegistry(final Invoker<?> originInvoker) {
        URL registryUrl = getRegistryUrl(originInvoker);
        return registryFactory.getRegistry(registryUrl);
}

先是又走了一遍getRegistryUrl(),然后就是通过registryFactory 获取Registry,其实这个registryFactory 是RegistryProtocol的一个成员,然后是dubbo spi 自动setter注入进来的。
我们来看一下registryFactory接口源代码:
在这里插入图片描述
我们可以看到@Adaptive的值是protocol,咱们上面的url中的protocol值正好是zookeeper,就可以找到ZookeeperRegistryFactory,我们看下ZookeeperRegistryFactory继承图
在这里插入图片描述
继承了一个抽象类AbstractRegistryFactory,然后getRegistry()方法就是在这个抽象类中,我们可以看下:

 // Registry Collection Map<RegistryAddress, Registry>
    private static final Map<String, Registry> REGISTRIES = new ConcurrentHashMap<String, Registry>();
@Override
    public Registry getRegistry(URL url) {
        url = url.setPath(RegistryService.class.getName())
                // interface
                .addParameter(Constants.INTERFACE_KEY, RegistryService.class.getName())
                // export  refer
                .removeParameters(Constants.EXPORT_KEY, Constants.REFER_KEY);
        String key = url.toServiceString();
        // Lock the registry access process to ensure a single instance of the registry
        LOCK.lock();
        try {
            // 从缓存中获取, 有就返回, 没有就创建
            Registry registry = REGISTRIES.get(key);
            if (registry != null) {
                return registry;
            }
            // 创建方法由子类实现  模板方法设计模式
            registry = createRegistry(url);
            if (registry == null) {
                throw new IllegalStateException("Can not create registry " + url);
            }
            REGISTRIES.put(key, registry);
            return registry;
        } finally {
            // Release the lock
            LOCK.unlock();
        }
    }
     // 由子类实现的 创建方法, 模板方法设计模式
    protected abstract Registry createRegistry(URL url);

前面就是设置参数,移除参数,然后将url转换成一个serviceKey的字符串,之后就是根据这个serviceKey去这个成员map中获取value,如果存在就返回,不存在就调用子类的createRegistry方法来创建Registry,然后再塞进去这个map中缓存。我们看下子类的createRegistry方法实现,这里就是ZookeeperRegistryFactory的实现
在这里插入图片描述
这里就是new了个ZookeeperRegistry对象然后返回了,这里zookeeperTransporter 成员是dubbo spi 创建完成这个对象自动注入的,这个咱们后面再解析。
我们接着RegistryProtocol#export 方法的解析,final URL registeredProviderUrl = getRegisteredProviderUrl(originInvoker);这行代码就是获取服务提供者的url,接着下面就是获取一个register的参数,缺省是true,
再接着就是往本地注册表注册,我们看下这个本地注册表ProviderConsumerRegTable。

2.ProviderConsumerRegTable#registerProvider

其实就是维护了两个map:
在这里插入图片描述
就是把这几个参数封装成ProviderInvokerWrapper对象,这个对象就是包装的作用,将这几个参数关联起来了,然后就是获取serviceKey,这个serviceKey就是暴露接口的全类名,然后就是根据serviceKey从providerInvokers 这个map中获取invokers,然后没有就创建,最后就是将包装的这个invoker缓存到invokers中了。
这个往本地注册表解析完了,我们再回到RegistryProtocol#export方法中,判断register,这里是true,然后走了register(registryUrl, registeredProviderUrl);,我们看下register方法,

 public void register(URL registryUrl, URL registedProviderUrl) {
        // 获取对应的 registry 对象
        Registry registry = registryFactory.getRegistry(registryUrl);
        //registedProviderUrl 是provider
        registry.register(registedProviderUrl);// 注册
    }

可以看出来,先是获取registry对象,这其实还是那个ZookeeperRegistry,然后就是调用ZookeeperRegistry#register 方法,这个咱们讲到注册中心部分再说。
接着ProviderConsumerRegTable.getProviderWrapper(originInvoker).setReg(true); // 设置注册标志,这行就是将刚刚塞到本地注册表中的invoker有个reg的属性设置成true表示注册了。
接着就是生成一个订阅的url,我们可以看下它的改动
在这里插入图片描述
在这里插入图片描述
接着就是创建一个listener,然后将这个listener缓存本地map中,这块这个listener我们解析注册中心的时候再解析,接着就是向注册中心订阅这个url。最后就是封装DestroyableExporter 对象返回。这个DestroyableExporter类封装了这几个成员。
在这里插入图片描述
然后实现了 unexport()方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

$码出未来

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值