8 - Dubbo本地服務暴露

騰一部分筆記到csdn

 

1. 本地暴露概述

 
 

2. 源碼分析

    在 3* - API 配置(二)之服務提供者 一文中,我們看到 ServiceConfig#export() 方法中,會在配置初始化完成後,調用順序圖的起點 #doExportUrls() 方法,循環registerURLs調用doExportUrlsFor1Protocol開始暴露服務。代碼如下:
2.1 doExportUrlsFor1Protocol
#doExportUrlsFor1Protocol(protocolConfig, registryURLs) 方法,基於單個協議,暴露服務。簡化代碼如下:
1/**
2:  * 基於單個協議,暴露服務
3:  *
4:  * @param protocolConfig 協議配置對象
5:  * @param registryURLs 註冊中心鏈接對象數組
6:  */
7private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
8:     // ... 【省略】 創建服務 URL 對象
10:     String scope = url.getParameter(Constants.SCOPE_KEY);
12:     if (!Constants.SCOPE_NONE.toString().equalsIgnoreCase(scope)) {
15:         if (!Constants.SCOPE_REMOTE.toString().equalsIgnoreCase(scope)) {
16:             exportLocal(url);
17:         }
19:         if (!Constants.SCOPE_LOCAL.toString().equalsIgnoreCase(scope)) {
20:             // ... 【省略】遠程暴露 
21:         }
22:     }
23:     this.urls.add(url);
24: }
 
ServiceConfig.java
-> 如果協議不等於Injvm,進行本地暴露。因爲Injvm的情況下,在InjvmProtocol遠程暴露時會暴露本地
-> URL local = URL.valueOf(url.toFullString()).setProtocol(Constants.LOCAL_PROTOCOL).setHost(LOCALHOST).setPort(0); //創建一個本地暴露的URL
-> ServiceClassHolder.getInstance().pushServiceClass(getServiceClass(ref)); //// 添加服務的真實類名,例如 DemoServiceImpl ,僅用於 RestProtocol 中。
 
-> Exporter<?> exporter = protocol.export(proxyFactory.getInvoker(ref, (Class) interfaceClass, local)); //本地暴露
    -> proxyFactory.getInvoker(ref, (Class) interfaceClass, local)
        -> extension = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.ProxyFactory.class).getExtension("javassist"); // SPI獲取Adaptive
        -> extension.getInvoker(arg0, arg1, arg2)
        JavassistProxyFactory.java
            -> final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type); //創建一個Wapper,這個Wapper列舉了所有對象的方法,減少了調用時反射的性能消耗
            -> return new AbstractProxyInvoker<T>(proxy, type, url) // AbstractProxyInvoker的inovke方法會把invocation的參數取出來調用wrapper來處理
 
    -> extension = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension("injvm"); //獲取Injvm協議
    -> extension.export(arg0)
    -> ProtocolFilterWrapper.export(arg0) // Protocol有包裝類 對應SPI的AOP
        -> 如果是註冊中心,不處理
    <----> 不是則return protocol.export(buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER));
            -> buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER) //對Invoker進行包裝一層filter
            ProtocolListenerWrapper.java
            -> ProtocolListenerWrapper.export
                -> 如果是註冊中心,不處理
                -> Exporter<T> exporter = protocol.export(invoker);
                    InjvmProtocol.java
                    -> return new InjvmExporter<T>(invoker, invoker.getUrl().getServiceKey(), exporterMap) //目的:exporterMap.put(key, this) key=com.alibaba.dubbo.demo.DemoService, this=InjvmExporter
                -> List<ExporterListener> listeners = Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(ExporterListener.class).getActivateExtension(invoker.getUrl(), Constants.EXPORTER_LISTENER_KEY)); //獲取Export監聽器
        <--------> return new ListenerExporterWrapper<T>(exporter, listeners);
 
-> exporters.add(exporter); //添加exporter
 

QA:
1.最後我們得到的exporter是一個什麼結構?
 
2.記錄下註冊中心的URL結構,和暴露協議不同這裏都是register協議,然後有個register=zookeeper這樣
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章