더보 소스 코드 분석 등록 센터

사육사 준비 :

  • Zookeeper 서버 측 다운로드 (여기에는 apache-zookeeper-3.5.5.tar.gz 다운로드가 아닌 구덩이가 있습니다) : http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.5.5/apache- 사육사-3.5.5-bin.tar.gz
  • {zookeeper_base} \ conf \ zoo_sample.cfg를 현재 디렉토리에 복사하고 이름을 zoo.cfg로 변경하십시오.
  • {zookeeper_base} \ bin \ zkServer.cmd 시작

클래스 상속 관계 :

  • RegistryService는 register register (URL url), unregister unregister (URL url), subscribe (URL url, NotifyListener listener), unsubscribe unsubscribe (URL url, NotifyListener listener), lookup (URL url))의 5 가지 인터페이스를 제공합니다.
  • FailbackRegistry는 RegistryService의 구현 클래스로, 구독 실패 및 구독 취소 실패 (시간이 지정된 작업을 사용하여 주기적으로 재시도)를 재 시도합니다. 또한 추상 메소드 doRegister (URL url), doUnregister (URL url), doSubscribe (URL url, NotifyListener listener), doUnsubscribe (URL url, NotifyListener listener)를 정의합니다.
  • ZookeeperRegistry는 등록, 취소, 구독 및 취소 메소드를 구현하는 FailbackRegistry 추상 클래스의 구현 클래스입니다.

Zookeeper는 구성 정보의 등록 및 검색을 담당하는 레지스트리입니다. dubbo 아키텍처에서는 서비스 등록 및 검색 구현 중 하나로서 주로 서비스 인터페이스 노출을 담당하며, 노드 구성을 통해 소비자는 서비스 제공자를 찾을 수 있습니다. 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