1. 程式人生 > >Dubbo原始碼學習--註冊中心(一)

Dubbo原始碼學習--註冊中心(一)

    目前Dubbo官方提供的註冊中心有Multicast、Zookeeper、Redis和Simple註冊中心,官方推薦使用Zookeeper作為生產環境的註冊中心。

    Dubbo官方也提供了擴充套件機制,開發人員可以根據自己的需要遵守一定的擴充套件規範開發自己的註冊中心,擴充套件介面主要有如下幾個介面:

  • com.alibaba.dubbo.registry.RegistryFactory
  • com.alibaba.dubbo.registry.Registry
  • com.alibaba.dubbo.registry.NotifyListener

擴充套件約定:

RegistryFactory.java:


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 註冊中心引用,總不返回空
     */
    Registry getRegistry(URL url); 
}

Registry介面繼承了RegistryService介面:

public interface RegistryService { // Registry extends RegistryService 
    /**
     * 註冊服務.
     * 
     * 註冊需處理契約:<br>
     * 1. 當URL設定了check=false時,註冊失敗後不報錯,在後臺定時重試,否則丟擲異常。<br>
     * 2. 當URL設定了dynamic=false引數,則需持久儲存,否則,當註冊者出現斷電等情況異常退出時,需自動刪除。<br>
     * 3. 當URL設定了category=overrides時,表示分類儲存,預設類別為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=overrides,只通知指定分類的資料,多個分類用逗號分隔,並允許星號通配,表示訂閱所有分類資料。<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);

}

NotifyListener.java

public interface NotifyListener { 
    /**
     * 當收到服務變更通知時觸發。
     * 
     * 通知需處理契約:<br>
     * 1. 總是以服務介面和資料型別為維度全量通知,即不會通知一個服務的同類型的部分資料,使用者不需要對比上一次通知結果。<br>
     * 2. 訂閱時的第一次通知,必須是一個服務的所有型別資料的全量通知。<br>
     * 3. 中途變更時,允許不同型別的資料分開通知,比如:providers, consumers, routes, overrides,允許只通知其中一種型別,但該型別的資料必須是全量的,不是增量的。<br>
     * 4. 如果一種型別的資料為空,需通知一個empty協議並帶category引數的標識性URL資料。<br>
     * 5. 通知者(即註冊中心實現)需保證通知的順序,比如:單執行緒推送,佇列序列化,帶版本對比。<br>
     * 
     * @param urls 已註冊資訊列表,總不為空,含義同{@link com.alibaba.dubbo.registry.RegistryService#lookup(URL)}的返回值。
     */
    void notify(List<URL> urls);

}

官方給出的擴充套件示例:

Maven專案結構:

src
 |-main
    |-java
        |-com
            |-xxx
                |-XxxRegistryFactoryjava (實現RegistryFactory介面)
                |-XxxRegistry.java (實現Registry介面)
    |-resources
        |-META-INF
            |-dubbo
                |-com.alibaba.dubbo.registry.RegistryFactory (純文字檔案,內容為:xxx=com.xxx.XxxRegistryFactory)

XxxRegistryFactory.java:

package com.xxx;

import com.alibaba.dubbo.registry.RegistryFactory;
import com.alibaba.dubbo.registry.Registry;
import com.alibaba.dubbo.common.URL;

public class XxxRegistryFactory implements RegistryFactory {
    public Registry getRegistry(URL url) {
        return new XxxRegistry(url);
    }
}

XxxRegistry.java:

package com.xxx;

import com.alibaba.dubbo.registry.Registry;
import com.alibaba.dubbo.registry.NotifyListener;
import com.alibaba.dubbo.common.URL;

public class XxxRegistry implements Registry {
    public void register(URL url) {
        // ...
    }
    public void unregister(URL url) {
        // ...
    }
    public void subscribe(URL url, NotifyListener listener) {
        // ...
    }
    public void unsubscribe(URL url, NotifyListener listener) {
        // ...
    }
}

META-INF/dubbo/com.alibaba.dubbo.registry.RegistryFactory:

xxx=com.xxx.XxxRegistryFactory