dubbo技術內(nèi)幕二 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() {
       //調(diào)用父類的unexport  其實啥也沒做
        super.unexport();
       //在本地緩存中remove掉
        exporterMap.remove(key);
    }

針對第二個exporter,調(diào)用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里面實現(xiàn)的,等于說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上進行刪除,這樣消費者監(jiān)聽到變化之后,將不再調(diào)用此本地服務
            zkClient.delete(toUrlPath(url));
        } catch (Throwable e) {
            throw new RpcException("Failed to unregister " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
        }
    }

同時對取消對該bean的配置信息的監(jiān)聽,如下

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

在我的pc上,其實就是取消對/dubbo/com.**.wms.dubbo.service.OrderCancelService/configurators路徑和其子節(jié)點的監(jiān)聽。
經(jīng)過如上的操作,該dubbo bean在zk上的信息都被清除了,現(xiàn)在需要清除本地的暴露信息,其實也是刪除本地的緩存信息,大家有信息可以去看下。源碼比較簡單。

dubbo bean的unexport主要影響的是消費端,消費端檢測到zk上面的注冊信息發(fā)生變化之后,也會實時的更新本地的緩存信息。后面我們會繼續(xù)的對dubbo的消費端的源碼進行分析
再貼一下取消的流程圖


image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 今天感恩節(jié)哎,感謝一直在我身邊的親朋好友。感恩相遇!感恩不離不棄。 中午開了第一次的黨會,身份的轉(zhuǎn)變要...
    余生動聽閱讀 10,803評論 0 11
  • 彩排完,天已黑
    劉凱書法閱讀 4,458評論 1 3
  • 表情是什么,我認為表情就是表現(xiàn)出來的情緒。表情可以傳達很多信息。高興了當然就笑了,難過就哭了。兩者是相互影響密不可...
    Persistenc_6aea閱讀 129,475評論 2 7

友情鏈接更多精彩內(nèi)容