ダボソースコード分析の登録センター

動物園の飼育係の準備:

  • Zookeeperサーバー側をダウンロードします(ここにピットがあり、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
  • {zookeeper_base} \ conf \ zoo_sample.cfgを現在のディレクトリにコピーし、名前をzoo.cfgに変更します。
  • {zookeeper_base} \ bin \ zkServer.cmdを起動します

クラス継承関係:

  • RegistryServiceは、5つのインターフェイスを提供します:登録登録(URL url)、登録解除(URL url)、購読(URL url、NotifyListenerリスナー)、購読解除(URL url、NotifyListenerリスナー)、ルックアップ(URL url)。
  • FailbackRegistryは、RegistryServiceの実装クラスであり、サブスクリプションの失敗とサブスクリプション解除の失敗の再試行を担当します(定期的なタスクを使用して定期的に再試行します)。また、抽象メソッドdoRegister(URL url)、doUnregister(URL url)、doSubscribe(URL url、NotifyListenerリスナー)、doUnsubscribe(URL url、NotifyListenerリスナー)も定義します。
  • ZookeeperRegistryは、FailbackRegistry抽象クラスの実装クラスであり、登録、キャンセル、サブスクリプション、およびキャンセルのメソッドを実装します。

Zookeeperはレジストリであり、構成情報の登録と検出を担当します。ダボのアーキテクチャでは、サービスの登録と検出の実装の1つであり、主にサービスインターフェイスの公開を担当します。ノードの構成を通じて、コンシューマーはサービスプロバイダーを見つけることができます。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);
                }
            }
        }
    }
}

ZookeeperClientのノードの作成、削除、および監視の操作を見てみましょう。

// 递归创建节点
// 除了叶节点是临时节点,其余节点都是永久节点(叶节点数据会定期更新可用的服务)
// 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);
}

おすすめ

転載: blog.csdn.net/fomeiherz/article/details/100984679