Dubbo源碼閱讀筆記2

来源:https://www.cnblogs.com/amwyyyy/archive/2018/01/25/8353518.html
-Advertisement-
Play Games

消費方初始化 消費方初始化的入口在ReferenceConfig類的get方法 前面基本和服務方的初始化一致 創建代理類,代理遠程方法實現 ...


### 消費方初始化

消費方初始化的入口在ReferenceConfig類的get方法
前面基本和服務方的初始化一致

public class ReferenceConfig<T> extends AbstractReferenceConfig {

    private static final long serialVersionUID = -5864351140409987595L;

    private static final Protocol refprotocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();

    private static final Cluster cluster = ExtensionLoader.getExtensionLoader(Cluster.class).getAdaptiveExtension();

    private static final ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
    private final List<URL> urls = new ArrayList<URL>();
    // 介面類型
    private String interfaceName;
    private Class<?> interfaceClass;
    // 客戶端類型
    private String client;
    // 點對點直連服務提供地址
    private String url;
    // 方法配置
    private List<MethodConfig> methods;
    // 預設配置
    private ConsumerConfig consumer;
    private String protocol;
    // 介面代理類引用
    private transient volatile T ref;
    // 介面調用器
    private transient volatile Invoker<?> invoker;
    // 是否已初始化
    private transient volatile boolean initialized;
    // 是否已銷毀
    private transient volatile boolean destroyed;
    
    // ...
}

public synchronized T get() {
    if (destroyed) {
        throw new IllegalStateException("Already destroyed!");
    }
    
    // 實現類引用不存在時初始化
    if (ref == null) {
        init();
    }
    return ref;
}

private void init() {
    // ...
    // 處理各種配置,放進map中
    
    //attributes通過系統context進行存儲.
    StaticContext.getSystemContext().putAll(attributes);
    
    // 生成代理(重點方法)
    ref = createProxy(map);
    
    // 將實現者和配置信息封裝成model
    ConsumerModel consumerModel = new ConsumerModel(getUniqueServiceName(), this, ref, interfaceClass.getMethods());
    // 放進全局context中
    ApplicationModel.initConsumerModele(getUniqueServiceName(), consumerModel);
}

創建代理類,代理遠程方法實現

private T createProxy(Map<String, String> map) {
    // 判斷是否要引用本地服務
    URL tmpUrl = new URL("temp", "localhost", 0, map);
    final boolean isJvmRefer;
    if (isInjvm() == null) {
        if (url != null && url.length() > 0) { //指定URL的情況下,不做本地引用
            isJvmRefer = false;
        } else if (InjvmProtocol.getInjvmProtocol().isInjvmRefer(tmpUrl)) {
            //預設情況下如果本地有服務暴露,則引用本地服務.
            isJvmRefer = true;
        } else {
            isJvmRefer = false;
        }
    } else {
        isJvmRefer = isInjvm().booleanValue();
    }

    if (isJvmRefer) {
        // 跟服務端的exportLocal對應
        URL url = new URL(Constants.LOCAL_PROTOCOL, NetUtils.LOCALHOST, 0, interfaceClass.getName()).addParameters(map);
        // 生成調用器,調用遠程方法實現
        invoker = refprotocol.refer(interfaceClass, url);
        if (logger.isInfoEnabled()) {
            logger.info("Using injvm service " + interfaceClass.getName());
        }
    } else {
        if (url != null && url.length() > 0) { // 用戶指定URL,指定的URL可能是對點對直連地址,也可能是註冊中心URL
            String[] us = Constants.SEMICOLON_SPLIT_PATTERN.split(url);
            if (us != null && us.length > 0) {
                for (String u : us) {
                    URL url = URL.valueOf(u);
                    if (url.getPath() == null || url.getPath().length() == 0) {
                        url = url.setPath(interfaceName);
                    }
                    if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
                        urls.add(url.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)));
                    } else {
                        urls.add(ClusterUtils.mergeUrl(url, map));
                    }
                }
            }
        } else { 
            // 通過註冊中心配置拼裝URL
            // 如:registry://127.0.0.1:6379/com.alibaba.dubbo.registry.RegistryService?application=demo-consumer&dubbo=2.0.0&file=${user.home}/.dubbo/dubbo-consumer.cache&owner=denis.huang&pid=15940&registry=redis&subscribe=true&timestamp=1513651178925
            List<URL> us = loadRegistries(false);
            if (us != null && us.size() > 0) {
                for (URL u : us) {
                    URL monitorUrl = loadMonitor(u);
                    if (monitorUrl != null) {
                        map.put(Constants.MONITOR_KEY, URL.encode(monitorUrl.toFullString()));
                    }
                    urls.add(u.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)));
                }
            }
            if (urls == null || urls.size() == 0) {
                throw new IllegalStateException("No such any registry to reference " + interfaceName + " on the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", please config <dubbo:registry address=\"...\" /> to your spring config.");
            }
        }

        if (urls.size() == 1) {
            invoker = refprotocol.refer(interfaceClass, urls.get(0));
        } else {
            List<Invoker<?>> invokers = new ArrayList<Invoker<?>>();
            URL registryURL = null;
            for (URL url : urls) {
                invokers.add(refprotocol.refer(interfaceClass, url));
                if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
                    registryURL = url; // 用了最後一個registry url
                }
            }
            if (registryURL != null) { // 有 註冊中心協議的URL
                // 對有註冊中心的Cluster 只用 AvailableCluster
                URL u = registryURL.addParameter(Constants.CLUSTER_KEY, AvailableCluster.NAME);
                invoker = cluster.join(new StaticDirectory(u, invokers));
            } else { // 不是 註冊中心的URL
                invoker = cluster.join(new StaticDirectory(invokers));
            }
        }
    }

    Boolean c = check;
    if (c == null && consumer != null) {
        c = consumer.isCheck();
    }
    if (c == null) {
        c = true; // default true
    }
    if (c && !invoker.isAvailable()) {
        throw new IllegalStateException("Failed to check the status of the service " + interfaceName + ". No provider available for the service " + (group == null ? "" : group + "/") + interfaceName + (version == null ? "" : ":" + version) + " from the url " + invoker.getUrl() + " to the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion());
    }
    if (logger.isInfoEnabled()) {
        logger.info("Refer dubbo service " + interfaceClass.getName() + " from url " + invoker.getUrl());
    }
    // 創建服務代理
    return (T) proxyFactory.getProxy(invoker);
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • QT5 TCP網路通訊 伺服器與客戶端建立連接listen() - connectToHost(); 觸發newPendingConnect信號 實時數據通訊write(); read(); 觸發readyRead信號 通訊主要使用的類: QTcpServer Class QTcpServer類提供 ...
  • 問題: 給定一個n*n的棋盤,棋盤中有一些位置不能放皇後。現在要向棋盤中放入n個黑皇後和n個白皇後,使任意的兩個黑皇後都不在同一行、同一列或同一條對角線上,任意的 兩個白皇後都不在同一行、同一列或同一條對角線上。問總共有多少種放法?n小於等於8。 輸入格式 輸入的第一行為一個整數n,表示棋盤的大小。 ...
  • 多註冊中心,一般用不到,但是某些情況下的確能解決不少問題,可以將某些dubbo服務註冊到2套dubbo系統中,實現服務在2套系統間的共用. 網上的配置說明很多,但包括dubbo官方說明文檔都是以xml文件配置方式舉例. 如想採用javaconfig的配置方式,則只需要對provider中的配置做適當 ...
  • session淺析 1.對於會話技術的理解 web會話技術包含Session和Cookie,會話技術是瀏覽器端與伺服器端的交互技術,拿cookie技術來說,客戶端在請求伺服器端的時候,如果有業務需要,伺服器會設置響應頭的key值與value值,在響應的時候帶給瀏覽器端,然後瀏覽器端在符合path條件 ...
  • 靜態頁面分為兩種,一種為jsp,另一種為html。 先看jsp的 在登陸的form表單中添加添加type為checkbox的input標簽 為該checkbox增加點擊事件 在後臺登錄方法中根據remember的值判斷是否設置Cookie 在頁面載入完後,獲取Cookie,並存入pageContex ...
  • import re # 正則表達式,用於提取數據 import requests # 下載網頁源代碼 ''' 安裝requests模塊:pip install requests 參考文檔:https://www.cnblogs.com/jamespan23/p/5526311.html ''' fo... ...
  • Logback介紹 Logback是由log4j創始人設計的又一個開源日誌組件。logback當前分成三個模塊:logback core,logback classic和logback access。logback core是其它兩個模塊的基礎模塊。logback classic是log4j的一個 ...
  • 擴展點載入(ExtensionLoader) 每一種類型的擴展點都有一個ExtensionLoader實例 1. 變數說明 2. 初始化 先從全局緩存裡面取,如果取不到則新建 ExtensionLoader構建方法,保存擴展點介面類型和對象工廠 擴展點對象工廠也是從通過ExtensionLoader ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...