The registration center of dubbo source code analysis

Zookeeper preparation:

  • Download Zookeeper server side (there is a pit here, not download apache-zookeeper-3.5.5.tar.gz): http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.5.5/apache-zookeeper- 3.5.5-bin.tar.gz
  • Copy {zookeeper_base}\conf\zoo_sample.cfg to the current directory and rename it to zoo.cfg
  • Start {zookeeper_base}\bin\zkServer.cmd

Class inheritance relationship:

  • RegistryService provides 5 interfaces: register register(URL url), unregister unregister(URL url), subscribe(URL url, NotifyListener listener), unsubscribe unsubscribe(URL url, NotifyListener listener), lookup(URL url).
  • FailbackRegistry is the implementation class of RegistryService, which is responsible for retrying of subscription failure and unsubscription failure (regular retry using timed tasks). It also defines abstract methods doRegister(URL url), doUnregister(URL url), doSubscribe(URL url, NotifyListener listener), doUnsubscribe(URL url, NotifyListener listener).
  • ZookeeperRegistry is the implementation class of the FailbackRegistry abstract class, which implements the methods of registration, cancellation, subscription, and cancellation.

Zookeeper is a registry, responsible for the registration and discovery of configuration information. In dubbo's architecture, it is one of the implementations of service registration and discovery, which is mainly responsible for service interface exposure. Through node configuration, consumers can find service providers. Let's analyze the source code of ZookeeperRegistry.

// 服务注册时,创建节点
protected void doRegister(URL url) {
    
    
    try {
    
    
        // ZookeeperClient zkClient
        // 后面会解析
        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);
    }
}

// 服务解注册,删除节点
protected void doUnregister(URL url) {
    
    
    try {
    
    
        // ZookeeperClient zkClient
        // 后面会解析
        zkClient.delete(toUrlPath(url));
    } catch (Throwable e) {
    
    
        throw new RpcException("Failed to unregister " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
    }
}

// 服务订阅
// ZookeeperRegistry#doSubscribe(final URL url, final NotifyListener listener)
protected void doSubscribe(final URL url, final NotifyListener listener) {
    
    
    try {
    
    
        if (Constants.ANY_VALUE.equals(url.getServiceInterface())) {
    
     // 订阅所有节点
            String root = toRootPath();
            ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url);
            if (listeners == null) {
    
    
                zkListeners.putIfAbsent(url, new ConcurrentHashMap<NotifyListener, ChildListener>());
                listeners = zkListeners.get(url);
            }
            ChildListener zkListener = listeners.get(listener);
            if (zkListener == null) {
    
    
                listeners.putIfAbsent(listener, new ChildListener() {
    
    
                    @Override
                    public void childChanged(String parentPath, List<String> currentChilds) {
    
    
                        for (String child : currentChilds) {
    
    
                            child = URL.decode(child);
                            if (!anyServices.contains(child)) {
    
    
                                anyServices.add(child);
                                subscribe(url.setPath(child).addParameters(Constants.INTERFACE_KEY, child,
                                        Constants.CHECK_KEY, String.valueOf(false)), listener);
                            }
                        }
                    }
                });
                zkListener = listeners.get(listener);
            }
            zkClient.create(root, false);
            List<String> services = zkClient.addChildListener(root, zkListener);
            if (services != null && !services.isEmpty()) {
    
    
                for (String service : services) {
    
    
                    service = URL.decode(service);
                    anyServices.add(service);
                    subscribe(url.setPath(service).addParameters(Constants.INTERFACE_KEY, service,
                            Constants.CHECK_KEY, String.valueOf(false)), listener);
                }
            }
        } else {
    
     // 订阅部分节点
            List<URL> urls = new ArrayList<URL>();
            for (String path : toCategoriesPath(url)) {
    
    
                // ConcurrentMap<URL, ConcurrentMap<NotifyListener, ChildListener>> zkListeners
                // 一个URL有一个ConcurrentMap<NotifyListener, ChildListener>
                // NotifyListener的实现类如RegistryDirectory
                // ChildListener对RegistryDirectory配置变动的监听,在其childChanged()对业务进行处理
                ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url);
                if (listeners == null) {
    
    
                    zkListeners.putIfAbsent(url, new ConcurrentHashMap<NotifyListener, ChildListener>());
                    listeners = zkListeners.get(url);
                }
                // 
                ChildListener zkListener = listeners.get(listener);
                // RegistryDirectory
                if (zkListener == null) {
    
    
                    // 创建监听器,监听节点变化
                    listeners.putIfAbsent(listener, new ChildListener() {
    
    
                        @Override
                        public void childChanged(String parentPath, List<String> currentChilds) {
    
    
                            // 有变更时会调用RegistryDirectory#notify(List<URL>)
                            ZookeeperRegistry.this.notify(url, listener, toUrlsWithEmpty(url, parentPath, currentChilds));
                        }
                    });
                    zkListener = listeners.get(listener);
                }
                // 创建持久化节点
                zkClient.create(path, false);
                // 为节点添加监听
                // 最终调用CuratorFramework#getChildren()#usingWatcher(listener)#forPath(path)进行监听
                List<String> children = zkClient.addChildListener(path, zkListener);
                if (children != null) {
    
    
                    urls.addAll(toUrlsWithEmpty(url, path, children));
                }
            }
            // 订阅时,会调用RegistryDirectory#notify(List<URL>)初始化
            notify(url, listener, urls);
        }
    } catch (Throwable e) {
    
    
        throw new RpcException("Failed to subscribe " + url + " to zookeeper " + getUrl() + ", cause: " + e.getMessage(), e);
    }
}

// 取消订阅
protected void doUnsubscribe(URL url, NotifyListener listener) {
    
    
    ConcurrentMap<NotifyListener, ChildListener> listeners = zkListeners.get(url);
    if (listeners != null) {
    
    
        ChildListener zkListener = listeners.get(listener);
        if (zkListener != null) {
    
    
            if (Constants.ANY_VALUE.equals(url.getServiceInterface())) {
    
     // 订阅所有节点
                String root = toRootPath();
                zkClient.removeChildListener(root, zkListener);
            } else {
    
    
                for (String path : toCategoriesPath(url)) {
    
    
                    // 删除监听
                    // ((CuratorWatcherImpl) listener).unwatch()
                    zkClient.removeChildListener(path, zkListener);
                }
            }
        }
    }
}

Let's take a look at the operations of ZookeeperClient's node creation, deletion, and monitoring.

// 递归创建节点
// 除了叶节点是临时节点,其余节点都是永久节点(叶节点数据会定期更新可用的服务)
// eg. /dubbo/com.alibaba.dubbo.demo.DemoService/providers/dubbo%3A%2F%2F10.0.75.1%3A20880%2Fcom.alibaba.dubbo.demo.DemoService%3Fanyhost%3Dtrue%26application%3Ddemo-provider%26bean.name%3Dcom.alibaba.dubbo.demo.DemoService%26dubbo%3D2.0.2%26generic%3Dfalse%26interface%3Dcom.alibaba.dubbo.demo.DemoService%26methods%3DsayHello%26pid%3D7160%26side%3Dprovider%26timestamp%3D1567860977014
// 创建节点有2种实现:CuratorZookeeperClient和ZkclientZookeeperClient,默认使用CuratorZookeeperClient实现
// AbstractZookeeperClient.create(String path, boolean ephemeral)
public void create(String path, boolean ephemeral) {
    
    
    if (!ephemeral) {
    
     // 非临时节点
        if (checkExists(path)) {
    
     // 已存在则不再创建
            return;
        }
    }
    int i = path.lastIndexOf('/');
    if (i > 0) {
    
     // 判断是否为最后一个
        // 递归创建节点
        create(path.substring(0, i), false);
    }
    if (ephemeral) {
    
     // 创建临时节点
        createEphemeral(path);
    } else {
    
     // 创建持久化节点
        createPersistent(path);
    }
}

// 为节点添加监听
public List<String> addChildListener(String path, final ChildListener listener) {
    
    
    ConcurrentMap<ChildListener, TargetChildListener> listeners = childListeners.get(path);
    if (listeners == null) {
    
    
        childListeners.putIfAbsent(path, new ConcurrentHashMap<ChildListener, TargetChildListener>());
        listeners = childListeners.get(path);
    }
    TargetChildListener targetListener = listeners.get(listener);
    if (targetListener == null) {
    
    
        listeners.putIfAbsent(listener, createTargetChildListener(path, listener));
        targetListener = listeners.get(listener);
    }
    // 调用子类添加监听
    // 默认实现是CuratorZookeeperClient#addTargetChildListener(path, targetListener)
    return addTargetChildListener(path, targetListener);
}

Guess you like

Origin blog.csdn.net/fomeiherz/article/details/100984679