大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

專注Java教育14年 全國咨詢/投訴熱線:400-8080-105
動力節點LOGO圖
始于2009,口口相傳的Java黃埔軍校
首頁 hot資訊 Dubbo注冊中心分析

Dubbo注冊中心分析

更新時間:2021-09-08 12:01:17 來源:動力節點 瀏覽1471次

注冊中心

關于注冊中心,Dubbo提供了多個實現方式,有比較成熟的使用zookeeper 和 redis 的實現,也有實驗性質的Multicast實現。

Zookeeper是Apacahe Hadoop的子項目,是一個樹型的目錄服務,支持變更推送,適合作為Dubbo服務的注冊中心,工業強度較高,可用于生產環境,

所以Zookeeper注冊中心也是Dubbo推薦使用也是使用度比較高的注冊中心。

Zookeeper注冊中心支持以下功能:

當提供者出現斷電等異常停機時,注冊中心能自動刪除提供者信息。

當注冊中心重啟時,能自動恢復注冊數據,以及訂閱請求。

當會話過期時,能自動恢復注冊數據,以及訂閱請求。

當設置 check="false" 時,記錄失敗注冊和訂閱請求,后臺定時重試。

可通過 username="admin" password="1234" 設置zookeeper登錄信息。

可通過 group="dubbo" 設置zookeeper的根節點,不設置將使用無根樹。

支持號通配符 group="" version="*" ,可訂閱服務的所有分組和所有版本的提供者。

源碼

zookeeper注冊中心的源碼為com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistry。

ZookeeperRegistry 類繼承自 FailbackRegistry,FailbackRegistry 又繼承自 AbstractRegistry,AbstractRegistry實現了 RegistryService 接口。

因此我們閱讀源碼順序為:RegistryService -> AbstractRegistry -> FailbackRegistry -> ZookeeperRegistry

RegistryService 接口

關于RegistryService接口RegistryService,Dubbo提供了詳細的注釋。

public interface RegistryService {
    /**
     * 注冊數據,比如:提供者地址,消費者地址,路由規則,覆蓋規則,等數據。
     * 
     * 注冊需處理契約:<br>
     * 1. 當URL設置了check=false時,注冊失敗后不報錯,在后臺定時重試,否則拋出異常。<br>
     * 2. 當URL設置了dynamic=false參數,則需持久存儲,否則,當注冊者出現斷電等情況異常退出時,需自動刪除。<br>
     * 3. 當URL設置了category=routers時,表示分類存儲,缺省類別為providers,可按分類部分通知數據。<br>
     * 4. 當注冊中心重啟,網絡抖動,不能丟失數據,包括斷線自動刪除數據。<br>
     * 5. 允許URI相同但參數不同的URL并存,不能覆蓋。<br>
     * 
     * @param url 注冊信息,不允許為空,如:dubbo://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&application=kylin
     */
    void register(URL url);
    /**
     * 取消注冊.
     * 
     * 取消注冊需處理契約:<br>
     * 1. 如果是dynamic=false的持久存儲數據,找不到注冊數據,則拋IllegalStateException,否則忽略。<br>
     * 2. 按全URL匹配取消注冊。<br>
     * 
     * @param url 注冊信息,不允許為空,如:dubbo://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&application=kylin
     */
    void unregister(URL url);
    /**
     * 訂閱符合條件的已注冊數據,當有注冊數據變更時自動推送.
     * 
     * 訂閱需處理契約:<br>
     * 1. 當URL設置了check=false時,訂閱失敗后不報錯,在后臺定時重試。<br>
     * 2. 當URL設置了category=routers,只通知指定分類的數據,多個分類用逗號分隔,并允許星號通配,表示訂閱所有分類數據。<br>
     * 3. 允許以interface,group,version,classifier作為條件查詢,如:interface=com.alibaba.foo.BarService&version=1.0.0<br>
     * 4. 并且查詢條件允許星號通配,訂閱所有接口的所有分組的所有版本,或:interface=*&group=*&version=*&classifier=*<br>
     * 5. 當注冊中心重啟,網絡抖動,需自動恢復訂閱請求。<br>
     * 6. 允許URI相同但參數不同的URL并存,不能覆蓋。<br>
     * 7. 必須阻塞訂閱過程,等第一次通知完后再返回。<br>
     * 
     * @param url 訂閱條件,不允許為空,如:consumer://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&application=kylin
     * @param listener 變更事件監聽器,不允許為空
     */
    void subscribe(URL url, NotifyListener listener);
    /**
     * 取消訂閱.
     * 
     * 取消訂閱需處理契約:<br>
     * 1. 如果沒有訂閱,直接忽略。<br>
     * 2. 按全URL匹配取消訂閱。<br>
     * 
     * @param url 訂閱條件,不允許為空,如:consumer://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&application=kylin
     * @param listener 變更事件監聽器,不允許為空
     */
    void unsubscribe(URL url, NotifyListener listener);
    /**
     * 查詢符合條件的已注冊數據,與訂閱的推模式相對應,這里為拉模式,只返回一次結果。
     * 
     * @see com.alibaba.dubbo.registry.NotifyListener#notify(List)
     * @param url 查詢條件,不允許為空,如:consumer://10.20.153.10/com.alibaba.foo.BarService?version=1.0.0&application=kylin
     * @return 已注冊信息列表,可能為空,含義同{@link com.alibaba.dubbo.registry.NotifyListener#notify(List<URL>)}的參數。
     */
    List<URL> lookup(URL url);
}

AbstractRegistry 抽象類

從構造函數可以看出 AbstractRegistry 抽象類主要是提供了對注冊中心數據的文件緩存。

    String filename = url.getParameter(Constants.FILE_KEY, System.getProperty("user.home") + "/.dubbo/dubbo-registry-" + url.getHost() + ".cache");
        File file = null;
        if (ConfigUtils.isNotEmpty(filename)) {
            file = new File(filename);
            if(! file.exists() && file.getParentFile() != null && ! file.getParentFile().exists()){
                if(! file.getParentFile().mkdirs()){
                    throw new IllegalArgumentException("Invalid registry store file " + file + ", cause: Failed to create directory " + file.getParentFile() + "!");
                }
            }
        }

Dubbo會在用戶目錄創建./dubbo文件夾及緩存文件,以windows為例,生成的緩存文件為:C:\Users\你的登錄用戶名/.dubbo/dubbo-registry-127.0.0.1.cache

FailbackRegistry 抽象類

FailbackRegistry 顧名思義是主要提供的是失敗自動恢復,同樣看一下構造函數,在構造函數中會通過 ScheduledExecutorService 一直執行Retry方法進行重試。

    public FailbackRegistry(URL url) {
        super(url);
        int retryPeriod = url.getParameter(Constants.REGISTRY_RETRY_PERIOD_KEY, Constants.DEFAULT_REGISTRY_RETRY_PERIOD);
        this.retryFuture = retryExecutor.scheduleWithFixedDelay(new Runnable() {
            public void run() {
                try {
                    retry();
                } catch (Throwable t) { 
                    logger.error("Unexpected error occur at failed retry, cause: " + t.getMessage(), t);
                }
            }
        }, retryPeriod, retryPeriod, TimeUnit.MILLISECONDS);
    }

retry()方法主要的從各個操作中的失敗列表取出失敗的操作進行重試。

  protected void retry() {
        if (! failedRegistered.isEmpty()) {
            Set<URL> failed = new HashSet<URL>(failedRegistered);
            if (failed.size() > 0) {
                if (logger.isInfoEnabled()) {
                    logger.info("Retry register " + failed);
                }
                try {
                    for (URL url : failed) {
                        try {
                            doRegister(url);
                            failedRegistered.remove(url);
                        } catch (Throwable t) { // 忽略所有異常,等待下次重試
                            logger.warn("Failed to retry register " + failed + ", waiting for again, cause: " + t.getMessage(), t);
                        }
                    }
                } catch (Throwable t) { // 忽略所有異常,等待下次重試
                    logger.warn("Failed to retry register " + failed + ", waiting for again, cause: " + t.getMessage(), t);
                }
            }
        }
        if(! failedUnregistered.isEmpty()) {
             //......
             doUnregister(url);
             failedUnregistered.remove(url);
             //.....
        }
        if (! failedSubscribed.isEmpty()) {
             //.....
        }
        if (! failedUnsubscribed.isEmpty()) {
            //.......
        }
        if (! failedNotified.isEmpty()) {
            //.......
        }
    }

同時提供了幾個抽象方法

ZookeeperRegistry 類

ZookeeperRegistry流程

服務提供者啟動時

向/dubbo/com.foo.BarService/providers目錄下寫入自己的URL地址。

服務消費者啟動時

訂閱/dubbo/com.foo.BarService/providers目錄下的提供者URL地址。

并向/dubbo/com.foo.BarService/consumers目錄下寫入自己的URL地址。

監控中心啟動時

訂閱/dubbo/com.foo.BarService目錄下的所有提供者和消費者URL地址。

ZookeeperRegistry 主要是實現了FailbackRegistry的那幾個抽象方法。本次也主要分析 doRegister(),doSubscribe()這兩個方法。

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);
        }
    }
    public void create(String path, boolean ephemeral) {
		int i = path.lastIndexOf('/');
		if (i > 0) {
			create(path.substring(0, i), false);
		}
		if (ephemeral) {
			createEphemeral(path);
		} else {
			createPersistent(path);
		}
	}
}

doRegister() 主要是調用zkClient創建一個節點。 create()以遞歸的方式創建節點,通過判斷Url中dynamic=false 判斷創建的是持久化節點還是臨時節點。

創建的結果為:

doSubscribe()

doSubscribe() 訂閱Zookeeper節點是通過創建ChildListener來實現的具體調用的方法是 addChildListener()

addChildListener()又調用 AbstractZookeeperClient.addTargetChildListener()然后調用subscribeChildChanges()

最后調用ZkclientZookeeperClient ZkClientd.watchForChilds()

    protected void doSubscribe(final URL url, final NotifyListener listener) {
        //....
        List<String> children = zkClient.addChildListener(path, zkListener);
        //.....
    }
    public List<String> addChildListener(String path, final ChildListener listener) {
        //......
		return addTargetChildListener(path, targetListener);
    }
    ```java
	public List<String> addTargetChildListener(String path, final IZkChildListener listener) {
		return client.subscribeChildChanges(path, listener);
	}
    public List<String> subscribeChildChanges(String path, IZkChildListener listener) {
        //.....
        return watchForChilds(path);
    }

以上就是動力節點小編介紹的"Dubbo注冊中心分析",希望對大家有幫助,想了解更多可查看Dubbo教程。動力節點在線學習教程,針對沒有任何Java基礎的讀者學習,讓你從入門到精通,主要介紹了一些Java基礎的核心知識,讓同學們更好更方便的學習和了解Java編程,感興趣的同學可以關注一下。

提交申請后,顧問老師會電話與您溝通安排學習

免費課程推薦 >>
技術文檔推薦 >>
主站蜘蛛池模板: 人成精品视频三区二区一区 | sihu影院永久在线影院 | 欧美片欧美日韩国产综合片 | 97午夜视频 | 成人午夜在线观看国产 | 亚洲成人中文字幕 | 成人aa在线观看视频 | 国产视频一区在线观看 | 欧美日韩中文亚洲v在线综合 | 九九热线精品视频18 | 国产一区二区三区免费观看 | 亚洲精品色综合色在线观看 | 国产野花视频天堂视频免费 | 九九精品免视看国产成人 | 看片不卡 | 国内精品一区二区 | 国产香蕉在线 | 97精品高清一区二区三区 | 日批日韩在线观看 | 美国成人毛片 | 欧美手机手机在线视频一区 | 视色视频 | 亚洲麻豆视频 | 一级特黄特黄的大片免费 | 日韩成人免费 | 国产精品伦理一区二区三区 | 色综合久久综合欧美综合图片 | 福利在线看片 | 七次郎在线视频精品视频 | 在线免费观看一级毛片 | 日本aaaa毛片在线看 | 免费国产午夜高清在线视频 | 欧美日韩亚洲国产一区二区三区 | 国产四虎 | 亚洲免费视频在线观看 | xxxwww欧美| 欧美91| 一级女性全黄生活片免费看 | 亚洲欧美一区二区三区综合 | 韩国美女高清爽快一级毛片 | 国产成人精品一区二区免费 |