1. 程式人生 > >dubbo原始碼深度解讀七之registery模組

dubbo原始碼深度解讀七之registery模組

前言:dubbo-registry是註冊中心模組,基於註冊中心下發地址的叢集方式,以及對各種註冊中心的抽象。Dubbo的註冊中心提供了多種實現,其實現是基於dubbo的spi的擴充套件機制的,我們也可以直接實現自己的註冊中心。

(一)dubbo-registry-api
(1)RegistryFactory

@SPI("dubbo")
public interface RegistryFactory {

    /**
     * 連線註冊中心.
     * 
     * 連線註冊中心需處理契約:<br>
     * 1. 當設定check=false時表示不檢查連線,否則在連線不上時丟擲異常。<br>
     * 2. 支援URL上的username:password許可權認證。<br>
     * 3. 支援backup=10.20.153.10備選註冊中心叢集地址。<br>
     * 4. 支援file=registry.cache本地磁碟檔案快取。<br>
     * 5. 支援timeout=1000請求超時設定。<br>
     * 6. 支援session=60000會話超時或過期設定。<br>
     * 
     * @param
url 註冊中心地址,不允許為空 * @return 註冊中心引用,總不返回空 */
@Adaptive({"protocol"}) Registry getRegistry(URL url);

類圖如下:
這裡寫圖片描述

RegistryFactory用來建立註冊中心, 預設的註冊中心是dubbo協議,由於阿里的註冊中心並沒有開源,dubbo協議註冊中心只提供了一個簡單實現。 開源dubbo的註冊中心推薦使用zookeeper。這裡我們主要去分析基於dubbo和zookeeper協議的註冊中心實現及使用。

(2)RegistryService
類圖如下:
這裡寫圖片描述


程式碼如下:

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); }

(二)註冊中心之Zookeeper協議註冊中心
服務的提供者和消費者在RegistryProtocol利用註冊中心暴露(export)和引用(refer)服務的時候會根據配置利用Dubbo的SPI機制獲取具體註冊中心註冊器
先檢視ZookeeperRegistryFactory的程式碼

public class ZookeeperRegistryFactory extends AbstractRegistryFactory {

    private ZookeeperTransporter zookeeperTransporter;

    public void setZookeeperTransporter(ZookeeperTransporter zookeeperTransporter) {
        this.zookeeperTransporter = zookeeperTransporter;
    }

    public Registry createRegistry(URL url) {
        return new ZookeeperRegistry(url, zookeeperTransporter);
    }

}

這裡建立zookeepr註冊器ZookeeperRegistry,ZookeeperTransporter是操作zookeepr的客戶端的工廠類,用來建立zookeeper客戶端,這裡客戶端並不是zookeeper原始碼的自帶的,而是採用第三方工具包,主要來簡化對zookeeper的操作,例如用zookeeper做註冊中心需要對zookeeper節點新增watcher做反向推送,但是每次回撥後節點的watcher都會被刪除,這些客戶會自動維護了這些watcher,在自動新增到節點上去。

接下來看ZookeeperRegistry的程式碼:

public ZookeeperRegistry(URL url, ZookeeperTransporter zookeeperTransporter) {
        super(url);
        if (url.isAnyHost()) {
            throw new IllegalStateException("registry address == null");
        }
        String group = url.getParameter(Constants.GROUP_KEY, DEFAULT_ROOT);
        if (! group.startsWith(Constants.PATH_SEPARATOR)) {
            group = Constants.PATH_SEPARATOR + group;
        }
        this.root = group;
        zkClient = zookeeperTransporter.connect(url);
        zkClient.addStateListener(new StateListener() {
            public void stateChanged(int state) {
                if (state == RECONNECTED) {
                    try {
                        recover();
                    } catch (Exception e) {
                        logger.error(e.getMessage(), e);
                    }
                }
            }
        });
    }

1.構造器利用客戶端建立了對zookeeper的連線,並且添加了自動回覆連線的監聽器。

2.註冊url就是利用客戶端在伺服器端建立url的節點,預設為臨時節點,客戶端與服務端斷開,幾點自動刪除

3.取消註冊的url,就是利用zookeeper客戶端刪除url節點

4.訂閱url, 功能是服務消費端訂閱服務提供方在zookeeper上註冊地址.

5 取消訂閱url, 只是去掉url上的註冊的監聽器

總結:這部分相對簡單理解,幾篇下來,已經對dubbo的各個模組有了基本的瞭解,接下來會進行整合,把思路連線起來,然後會分析一些好的設計模式等等,最後就會進行改造了,對於改造有什麼想法的,歡迎私信我。