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<String> anyServices = new ConcurrentHashSet<String>();
18: /**
19: * 监听器集合
20: */
21: private final ConcurrentMap<URL, ConcurrentMap<NotifyListener, ChildListener>> zkListeners = new ConcurrentHashMap<URL, ConcurrentMap<NotifyListener, ChildListener>>();
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<NotifyListener, ChildListener> listeners = zkListeners.get(url);
9: if (listeners == null) { // 不存在,进行创建
10: zkListeners.putIfAbsent(url, new ConcurrentHashMap<NotifyListener, ChildListener>());
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<String> 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<String> 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<URL> urls = new ArrayList<URL>();
48: // 循环分类数组
49: for (String path : toCategoriesPath(url)) {
50: // 获得 url 对应的监听器集合
51: ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url);
52: if (listeners == null) { // 不存在,进行创建
53: zkListeners.putIfAbsent(url, new ConcurrentHashMap<NotifyListener, ChildListener>());
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<String> 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<String> 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: }