dubbo技術(shù)內(nèi)幕十四 serviceBean export向zk寫了什么

前面的章節(jié)里面對zk的介紹很少咖刃,這邊會介紹serviceBean在export的過程中僵缺,到底向zk寫了什么磕潮,以及訂閱了什么容贝。zk的功能無非是信息的存儲和變更通知。
我們還是從ServiceBean的export方法進(jìn)行跟蹤斤富。會一直的跟蹤到ServiceConfig類的doExportUrls方法。如下

private void doExportUrls() {
        List<URL> registryURLs = loadRegistries(true);
        for (ProtocolConfig protocolConfig : protocols) {
            doExportUrlsFor1Protocol(protocolConfig, registryURLs);
        }
    }

由于我們只配置了zk一個注冊中心焕参,registryURLs返回如下


image.png

在ServiceConfig的doExportUrlsFor1Protocol方法的三句非常重要

Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));
 DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
Exporter<?> exporter = protocol.export(wrapperInvoker)

前兩句就是將此ref封裝成Invoker叠纷,只有將ref封裝成Invoker之后,才會將此invoker的信息寫入到zk里面去崇众。


image.png

由于Invoker里面封裝的url的protocol為registry航厚,不難猜出。

Exporter<?> exporter = protocol.export(wrapperInvoker);

會調(diào)到RegistryProtocol類的export方法眯漩。那么核心的方法都封裝在RegistryProtocol類的export方法,如下

public <T> Exporter<T> export(final Invoker<T> originInvoker) throws RpcException {
        //export invoker 在本地暴露的意思是坤塞,在本地啟動一個nettyService進(jìn)行暴露
        final ExporterChangeableWrapper<T> exporter = doLocalExport(originInvoker);
        //拿到zk的地址
        URL registryUrl = getRegistryUrl(originInvoker);

        //registry provider   這個就是注冊provider
        //根據(jù)originInvoker的url拿到Registry  ZookeeperRegistry(其實(shí)就是連接zk service 
          的客戶端,里面封裝了各種的信息)
        final Registry registry = getRegistry(originInvoker);
        //服務(wù)端暴露的dubbo服務(wù)的本地信息
        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);
    }

其實(shí)上面的這個方法,就兩個目的
1 在本地進(jìn)行暴露份汗,啟動nettySevice蝴簇,這個在前面已經(jīng)講過了,這里帶過
2 在zk上面進(jìn)行注冊旁钧,這樣消費(fèi)者就能看到自己互拾。

我們看下 register(registryUrl, registeredProviderUrl)方法

 public void register(URL registryUrl, URL registedProviderUrl) {
        //這個就是前面說的ZookeeperRegistry
        Registry registry = registryFactory.getRegistry(registryUrl);
     //registedProviderUrl,這個就是本地dubbo服務(wù)的url信息。
        registry.register(registedProviderUrl);
    }

而 registry.register(registedProviderUrl);最終會進(jìn)入到ZookeeperRegistry的doRegister方法颜矿,如下

    protected void doRegister(URL url) {
        try {
            zkClient.create(toUrlPath(url), url.getParameter(Constants.DYNAMIC_KEY, true));
        } catch (Throwable e) {
            throw new RpcException("Failed to register " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
        }
    }

而toUrlPath(url)返回值為,如下


image.png

可以看到田篇,我們再
/dubbo/com.ilsp.order.service.ContractService/providers節(jié)點(diǎn)下添加了此dubbo服務(wù)的本地信息。
經(jīng)過這步之后泊柬,那消費(fèi)者通過查詢/dubbo/com.ilsp.order.service.ContractService/providers節(jié)點(diǎn)就知道有哪些消費(fèi)者進(jìn)行注冊了彬呻。
而在RegistryProtocol類的export方法里面還有一句重要的語句

registry.subscribe(overrideSubscribeUrl, overrideSubscribeListener);

overrideSubscribeUrl路徑添加監(jiān)聽器overrideSubscribeListener進(jìn)行監(jiān)聽。
而這個方法最終也會進(jìn)入ZookeeperRegistry的doSubscribe方法闸氮,源碼如下

protected void doSubscribe(final URL url, final NotifyListener listener) {
        try {
            if (Constants.ANY_VALUE.equals(url.getServiceInterface())) {
                String root = toRootPath();
                ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url);
                if (listeners == null) {
                    zkListeners.putIfAbsent(url, new ConcurrentHashMap<NotifyListener, ChildListener>());
                    listeners = zkListeners.get(url);
                }
                ChildListener zkListener = listeners.get(listener);
                if (zkListener == null) {
                    listeners.putIfAbsent(listener, new ChildListener() {
                        @Override
                        public void childChanged(String parentPath, List<String> currentChilds) {
                            for (String child : currentChilds) {
                                child = URL.decode(child);
                                if (!anyServices.contains(child)) {
                                    anyServices.add(child);
                                    subscribe(url.setPath(child).addParameters(Constants.INTERFACE_KEY, child,
                                            Constants.CHECK_KEY, String.valueOf(false)), listener);
                                }
                            }
                        }
                    });
                    zkListener = listeners.get(listener);
                }
                zkClient.create(root, false);
                List<String> services = zkClient.addChildListener(root, zkListener);
                if (services != null && !services.isEmpty()) {
                    for (String service : services) {
                        service = URL.decode(service);
                        anyServices.add(service);
                        subscribe(url.setPath(service).addParameters(Constants.INTERFACE_KEY, service,
                                Constants.CHECK_KEY, String.valueOf(false)), listener);
                    }
                }
            } else {
                List<URL> urls = new ArrayList<URL>();
               //path就是/dubbo/com.ilsp.order.service.ContractService/configurators
                for (String path : toCategoriesPath(url)) {
                    ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url);
                    if (listeners == null) {
                        zkListeners.putIfAbsent(url, new ConcurrentHashMap<NotifyListener, ChildListener>());
                        listeners = zkListeners.get(url);
                    }
                    ChildListener zkListener = listeners.get(listener);
                    if (zkListener == null) {
                        listeners.putIfAbsent(listener, new ChildListener() {
                            @Override
                            public void childChanged(String parentPath, List<String> currentChilds) {
                                ZookeeperRegistry.this.notify(url, listener, toUrlsWithEmpty(url, parentPath, currentChilds));
                            }
                        });
                        zkListener = listeners.get(listener);
                    }
                    //創(chuàng)建/dubbo/com.ilsp.order.service.ContractService/configurators的zk path
                    zkClient.create(path, false);
                   //對該path添加監(jiān)聽器
                    List<String> children = zkClient.addChildListener(path, zkListener);
                    if (children != null) {
                        urls.addAll(toUrlsWithEmpty(url, path, children));
                    }
                }
                //回調(diào)監(jiān)聽器
                notify(url, listener, urls);
            }
        } catch (Throwable e) {
            throw new RpcException("Failed to subscribe " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
        }
    }

而這個notify(url, listener, urls)會回調(diào)到RegistryProtocol的內(nèi)部私有類OverrideListener剪况。
如果configurators的配置發(fā)生了修改,同時也會修改本地暴露的dubbo服務(wù)的信息蒲跨。
如果我們打開dubbo控制臺译断,對于dubbo服務(wù)來說,只關(guān)心如下的兩項(xiàng)或悲。


image.png

ok 下一篇我們會看下 當(dāng)ReferenceBean在refer的時候孙咪,到底想zk寫了什么,訂閱了什么

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末巡语,一起剝皮案震驚了整個濱河市翎蹈,隨后出現(xiàn)的幾起案子男公,更是在濱河造成了極大的恐慌枢赔,老刑警劉巖踏拜,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件速梗,死亡現(xiàn)場離奇詭異镀琉,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)烁设,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進(jìn)店門副瀑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來糠睡,“玉大人疚颊,你說我怎么就攤上這事材义。” “怎么了油挥?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長贤牛。 經(jīng)常有香客問我盔夜,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任椭微,我火速辦了婚禮蝇率,結(jié)果婚禮上本慕,老公的妹妹穿的比我還像新娘锅尘。我一直安慰自己藤违,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布议街。 她就那樣靜靜地躺著特漩,像睡著了一般骨杂。 火紅的嫁衣襯著肌膚如雪腊脱。 梳的紋絲不亂的頭發(fā)上陕凹,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天杜耙,我揣著相機(jī)與錄音,去河邊找鬼记靡。 笑死摸吠,一個胖子當(dāng)著我的面吹牛寸痢,可吹牛的內(nèi)容都是我干的紊选。 我是一名探鬼主播兵罢,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼巩那,長吁一口氣:“原來是場噩夢啊……” “哼拢操!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起杠园,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤抛蚁,失蹤者是張志新(化名)和其女友劉穎瞧甩,沒想到半個月后肚逸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體朦促,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡务冕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了箩退。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片佳谦。...
    茶點(diǎn)故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖胧瓜,靈堂內(nèi)的尸體忽然破棺而出府喳,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站孔轴,受9級特大地震影響路鹰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜晋柱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一钦椭、第九天 我趴在偏房一處隱蔽的房頂上張望彪腔。 院中可真熱鬧漫仆,春花似錦盲厌、人聲如沸吗浩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽阀湿。三九已至陷嘴,卻和暖如春间坐,著一層夾襖步出監(jiān)牢的瞬間邑退,已是汗流浹背地技。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工莫矗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留溯警,地道東北人梯轻。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓彬伦,卻偏偏與公主長得像单绑,于是被迫代替她去往敵國和親曹宴。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容