Dubbo源码分析之zookeeper注册中心

1.ZookeeperRegistryFactory

com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistryFactory ,实现 AbstractRegistryFactory 抽象类,Zookeeper Registry 工厂。代码如下:

public class ZookeeperRegistryFactory extends AbstractRegistryFactory {

    /**
     * Zookeeper 工厂
     */
    private ZookeeperTransporter zookeeperTransporter;

    /**
     * 设置 Zookeeper 工厂
     *
     * 该方法,通过 Dubbo SPI 注入
     *
     * @param zookeeperTransporter Zookeeper 工厂对象
     */
    public void setZookeeperTransporter(ZookeeperTransporter zookeeperTransporter) {
        this.zookeeperTransporter = zookeeperTransporter;
    }

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

}

3. ZookeeperRegistry

com.alibaba.dubbo.registry.zookeeper.ZookeeperRegistry ,实现 FailbackRegistry 抽象类,Zookeeper Registry 。

3.1 属性 + 构造方法

 1: /**
 2:  * 默认端口
 3:  */
 4: private final static int DEFAULT_ZOOKEEPER_PORT = 2181;
 5: /**
 6:  * 默认 Zookeeper 根节点
 7:  */
 8: private final static String DEFAULT_ROOT = "dubbo";
 9: 
10: /**
11:  * Zookeeper 根节点
12:  */
13: private final String root;
14: /**
15:  * Service 接口全名集合
16:  */
17: private final Set anyServices = new ConcurrentHashSet();
18: /**
19:  * 监听器集合
20:  */
21: private final ConcurrentMap> zkListeners = new ConcurrentHashMap>();
22: /**
23:  * Zookeeper 客户端
24:  */
25: private final ZookeeperClient zkClient;
26: 
27: public ZookeeperRegistry(URL url, ZookeeperTransporter zookeeperTransporter) {
28:     super(url);
29:     if (url.isAnyHost()) {
30:         throw new IllegalStateException("registry address == null");
31:     }
32:     // 获得 Zookeeper 根节点
33:     String group = url.getParameter(Constants.GROUP_KEY, DEFAULT_ROOT); // `url.parameters.group` 参数值
34:     if (!group.startsWith(Constants.PATH_SEPARATOR)) {
35:         group = Constants.PATH_SEPARATOR + group;
36:     }
37:     this.root = group;
38:     // 创建 Zookeeper Client
39:     zkClient = zookeeperTransporter.connect(url);
40:     // 添加 StateListener 对象。该监听器,在重连时,调用恢复方法。
41:     zkClient.addStateListener(new StateListener() {
42:         public void stateChanged(int state) {
43:             if (state == RECONNECTED) {
44:                 try {
45:                     recover();
46:                 } catch (Exception e) {
47:                     logger.error(e.getMessage(), e);
48:                 }
49:             }
50:         }
51:     });
52: }
  • root 属性,Zookeeper 根节点,即首图的 Root 层。
  • anyServices 属性,Service 接口接口全名集合。该属性适可用于监控中心,订阅整个 Service 层。因为,Service 层是动态的,可以有不断有新的 Service 服务发布(注意,不是服务实例)。在 #doSubscribe(url, notifyListener) 方法中,会更容易理解。
  • zkListeners 属性,监听器集合,建立 NotifyListener 和 ChildListener 的映射关系。
  • zkClient 属性,Zookeeper 客户端。
  • 构造方法
    • 第 28 至 31 行:设置注册中心的 URL 。
    • 第 32 至 37 行:设置在 Zookeeper 的根节点,缺省使用 DEFAULT_ROOT 。
    • 第 39 行:调用 ZookeeperTransporter#connect(url) 方法,基于 Dubbo SPI Adaptive 机制,根据 url 参数,加载对应的 ZookeeperTransporter 实现类,创建对应的 ZookeeperClient 实现类的对应。
    • 第 41 至 51 行:添加 StateListener 对象到 ZookeeperClient 对象中。该监听器,在重连时,在第 45 行的代码,调用 #recover() 方法,进行恢复逻辑,重新发起注册和订阅。

3.2 doRegister

1: @Override
2: protected void doRegister(URL url) {
3:     try {
4:         zkClient.create(toUrlPath(url), url.getParameter(Constants.DYNAMIC_KEY, true));
5:     } catch (Throwable e) {
6:         throw new RpcException("Failed to register " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
7:     }
8: }
  • 第 4 行:调用 #toUrlPath(url) 方法,获得 URL 的路径。
  • 第 4 行:url.parameters.dynamic ,是否动态数据。若为 false ,该数据为持久数据,当注册方退出时,数据依然保存在注册中心。
  • 第 4 行:调用 ZookeeperClient#create(url, ephemeral) 方法,创建 URL 节点,即我们在首图看到的 URL 层

3.2.1 toUrlPath

/**
 * 获得 URL 的路径
 *
 * Root + Service + Type + URL
 *
 * 被 {@link #doRegister(URL)} 和 {@link #doUnregister(URL)} 调用
 *
 * @param url URL
 * @return 路径
 */
private String toUrlPath(URL url) {
    return toCategoryPath(url) + Constants.PATH_SEPARATOR + URL.encode(url.toFullString());
}

3.2.2 toCategoryPath

/**
 * 获得分类路径
 *
 * Root + Service + Type
 *
 * @param url URL
 * @return 分类路径
 */
private String toCategoryPath(URL url) {
    return toServicePath(url) + Constants.PATH_SEPARATOR + url.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY);
}

3.2.3 toServicePath

/**
 * 获得服务路径
 *
 * Root + Type
 *
 * @param url URL
 * @return 服务路径
 */
private String toServicePath(URL url) {
    String name = url.getServiceInterface();
    if (Constants.ANY_VALUE.equals(name)) {
        return toRootPath();
    }
    return toRootDir() + URL.encode(name);
}

3.2.4 toRootDir

/**
 * 获得根目录
 *
 * Root
 *
 * @return 路径
 */
private String toRootDir() {
    if (root.equals(Constants.PATH_SEPARATOR)) {
        return root;
    }
    return root + Constants.PATH_SEPARATOR;
}

/**
 * Root
 *
 * @return 根路径
 */
private String toRootPath() {
    return root;
}

3.3 doUnregister

@Override
protected void doUnregister(URL url) {
    try {
        zkClient.delete(toUrlPath(url));
    } catch (Throwable e) {
        throw new RpcException("Failed to unregister " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
    }
}

3.4 doSubscribe

 1: @Override
 2: protected void doSubscribe(final URL url, final NotifyListener listener) {
 3:     try {
 4:         // 处理所有 Service 层的发起订阅,例如监控中心的订阅
 5:         if (Constants.ANY_VALUE.equals(url.getServiceInterface())) {
 6:             String root = toRootPath();
 7:             // 获得 url 对应的监听器集合
 8:             ConcurrentMap listeners = zkListeners.get(url);
 9:             if (listeners == null) { // 不存在,进行创建
10:                 zkListeners.putIfAbsent(url, new ConcurrentHashMap());
11:                 listeners = zkListeners.get(url);
12:             }
13:             // 获得 ChildListener 对象
14:             ChildListener zkListener = listeners.get(listener);
15:             if (zkListener == null) { // 不存在 ChildListener 对象,进行创建 ChildListener 对象
16:                 listeners.putIfAbsent(listener, new ChildListener() {
17:                     public void childChanged(String parentPath, List currentChilds) {
18:                         for (String child : currentChilds) {
19:                             child = URL.decode(child);
20:                             // 新增 Service 接口全名时(即新增服务),发起该 Service 层的订阅
21:                             if (!anyServices.contains(child)) {
22:                                 anyServices.add(child);
23:                                 subscribe(url.setPath(child).addParameters(Constants.INTERFACE_KEY, child,
24:                                         Constants.CHECK_KEY, String.valueOf(false)), listener);
25:                             }
26:                         }
27:                     }
28:                 });
29:                 zkListener = listeners.get(listener);
30:             }
31:             // 创建 Service 节点。该节点为持久节点。
32:             zkClient.create(root, false);
33:             // 向 Zookeeper ,Service 节点,发起订阅
34:             List services = zkClient.addChildListener(root, zkListener);
35:             // 首次全量数据获取完成时,循环 Service 接口全名数组,发起该 Service 层的订阅
36:             if (services != null && !services.isEmpty()) {
37:                 for (String service : services) {
38:                     service = URL.decode(service);
39:                     anyServices.add(service);
40:                     subscribe(url.setPath(service).addParameters(Constants.INTERFACE_KEY, service,
41:                             Constants.CHECK_KEY, String.valueOf(false)), listener);
42:                 }
43:             }
44:         // 处理指定 Service 层的发起订阅,例如服务消费者的订阅
45:         } else {
46:             // 子节点数据数组
47:             List urls = new ArrayList();
48:             // 循环分类数组
49:             for (String path : toCategoriesPath(url)) {
50:                 // 获得 url 对应的监听器集合
51:                 ConcurrentMap listeners = zkListeners.get(url);
52:                 if (listeners == null) { // 不存在,进行创建
53:                     zkListeners.putIfAbsent(url, new ConcurrentHashMap());
54:                     listeners = zkListeners.get(url);
55:                 }
56:                 // 获得 ChildListener 对象
57:                 ChildListener zkListener = listeners.get(listener);
58:                 if (zkListener == null) { // 不存在 ChildListener 对象,进行创建 ChildListener 对象
59:                     listeners.putIfAbsent(listener, new ChildListener() {
60:                         public void childChanged(String parentPath, List currentChilds) {
61:                             // 变更时,调用 `#notify(...)` 方法,回调 NotifyListener
62:                             ZookeeperRegistry.this.notify(url, listener, toUrlsWithEmpty(url, parentPath, currentChilds));
63:                         }
64:                     });
65:                     zkListener = listeners.get(listener);
66:                 }
67:                 // 创建 Type 节点。该节点为持久节点。
68:                 zkClient.create(path, false);
69:                 // 向 Zookeeper ,PATH 节点,发起订阅
70:                 List children = zkClient.addChildListener(path, zkListener);
71:                 // 添加到 `urls` 中
72:                 if (children != null) {
73:                     urls.addAll(toUrlsWithEmpty(url, path, children));
74:                 }
75:             }
76:             // 首次全量数据获取完成时,调用 `#notify(...)` 方法,回调 NotifyListener
77:             notify(url, listener, urls);
78:         }
79:     } catch (Throwable e) {
80:         throw new RpcException("Failed to subscribe " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
81:     }
82: }

你可能感兴趣的:(dubbo,dubbo)