dubbo技术内幕二 serviceBean unexport过程

既然有dubbo bean的export功能,那么就有dubbo bean的unexport功能,如果我们也将dubbo bean的unexport的功能搞清楚,我们可以设计一个非常牛的debug小插件,这个留到后面讲。
ServiceBean的父类ServiceConfig提供了注销bean的方法,如下

Class ServiceConfig
 public synchronized void unexport() {
        if (!exported) {
            return;
        }
        if (unexported) {
            return;
        }
        if (!exporters.isEmpty()) {
            for (Exporter<?> exporter : exporters) {
                try {
                    exporter.unexport();
                } catch (Throwable t) {
                    logger.warn("unexpected err when unexport" + exporter, t);
                }
            }
            exporters.clear();
        }
        unexported = true;
    }

其中exporters是在上一篇介绍的暴露的两个export,如下图


image.png

我们接下来看下每个exporter具体是怎么unexport的,对一个类型为InjvmExporter

Class  InjvmExporter
 public void unexport() {
       //调用父类的unexport  其实啥也没做
        super.unexport();
       //在本地缓存中remove掉
        exporterMap.remove(key);
    }

针对第二个exporter,调用unexport进入到RegistryProtocol

Class  RegistryProtocol

            Registry registry = RegistryProtocol.INSTANCE.getRegistry(originInvoker);
            try {
                //这个registry真实是ZookeeperRegistry
                registry.unregister(registerUrl);
            } catch (Throwable t) {
                logger.warn(t.getMessage(), t);
            }
            try {
                NotifyListener listener = RegistryProtocol.INSTANCE.overrideListeners.remove(subscribeUrl);
                registry.unsubscribe(subscribeUrl, listener);
            } catch (Throwable t) {
                logger.warn(t.getMessage(), t);
            }

            executor.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        int timeout = ConfigUtils.getServerShutdownTimeout();
                        if (timeout > 0) {
                            logger.info("Waiting " + timeout + "ms for registry to notify all consumers before unexport. Usually, this is called when you use dubbo API");
                            Thread.sleep(timeout);
                        }
                        exporter.unexport();
                    } catch (Throwable t) {
                        logger.warn(t.getMessage(), t);
                    }
                }
            });
        }

其中ZookeeperRegistry的unregister是在父类FailbackRegistry里面实现的,等于说zk的操作都是默认是failback(失败重试机制),代码如下(省略了不相关的代码)

public void unregister(URL url) {
       //在父类缓存中将缓存的url删除
        super.unregister(url);
           // Sending a cancellation request to the server side
            doUnregister(url);
       
    }

如下,使用zkClient将

Class ZookeeperRegistry
 protected void doUnregister(URL url) {
        try {
            //将注册信息在zk上进行删除,这样消费者监听到变化之后,将不再调用此本地服务
            zkClient.delete(toUrlPath(url));
        } catch (Throwable e) {
            throw new RpcException("Failed to unregister " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
        }
    }

同时对取消对该bean的配置信息的监听,如下

 NotifyListener listener = RegistryProtocol.INSTANCE.overrideListeners.remove(subscribeUrl);
                registry.unsubscribe(subscribeUrl, listener);

在我的pc上,其实就是取消对/dubbo/com.**.wms.dubbo.service.OrderCancelService/configurators路径和其子节点的监听。
经过如上的操作,该dubbo bean在zk上的信息都被清除了,现在需要清除本地的暴露信息,其实也是删除本地的缓存信息,大家有信息可以去看下。源码比较简单。

dubbo bean的unexport主要影响的是消费端,消费端检测到zk上面的注册信息发生变化之后,也会实时的更新本地的缓存信息。后面我们会继续的对dubbo的消费端的源码进行分析
再贴一下取消的流程图


image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 今天感恩节哎,感谢一直在我身边的亲朋好友。感恩相遇!感恩不离不弃。 中午开了第一次的党会,身份的转变要...
    余生动听阅读 13,609评论 0 11
  • 彩排完,天已黑
    刘凯书法阅读 9,808评论 1 3
  • 表情是什么,我认为表情就是表现出来的情绪。表情可以传达很多信息。高兴了当然就笑了,难过就哭了。两者是相互影响密不可...
    Persistenc_6aea阅读 128,350评论 2 7

友情链接更多精彩内容