Dubbo源码解析十一:注册中心

在这里插入图片描述

介绍

dubbo注册中心的代码定义在dubbo-registry模块中,可以看到dubbo可以使用consul,redis,zookeeper来实现注册中心。default是基于内存实现的注册中心,multicast是基于广播实现的注册中心。
在这里插入图片描述
Registry继承了RegistryService接口,RegistryService接口定义了对注册中心的基本操作

public interface RegistryService {
    
    

    // 注册
    void register(URL url);

    // 注销
    void unregister(URL url);

    // 订阅
    void subscribe(URL url, NotifyListener listener);

    // 退订
    void unsubscribe(URL url, NotifyListener listener);

    // 查找服务地址
    List<URL> lookup(URL url);

}

可以看到订阅和退订的时候,传入了一个NotifyListener接口,当订阅或者退订的动作发生时,会回掉这个接口

继承关系如下图
在这里插入图片描述
AbstractRegistry对注册中心的内容进行了缓存,这样能保证当注册中心不可用的时候,还能正常提供服务

register和subscribe等操作比较简单,就是往缓存中添加删除服务,往缓存中添加删除对应的监听器。

FailbackRegistry增加了重试机制

注册中心是如何创建的?

注册中心的创建是通过工厂模式来实现的,每种注册中心的实现对应一种工厂类
在这里插入图片描述

@SPI("dubbo")
public interface RegistryFactory {
    
    

    @Adaptive({
    
    "protocol"})
    Registry getRegistry(URL url);

}

可以看到具体的工厂类实现都继承了AbstractRegistryFactory,来看一下AbstractRegistryFactory做了哪些操作?

public Registry getRegistry(URL url) {
    
    
    // 省略部分代码
    // 只有一个线程创建服务注册实例
    LOCK.lock();
    try {
    
    
        // 访问缓存
        Registry registry = REGISTRIES.get(key);
        if (registry != null) {
    
    
            return registry;
        }
        //create registry by spi/ioc
        // 是个抽象方法,子类来实现具体的创建过程
        registry = createRegistry(url);
        if (registry == null) {
    
    
            throw new IllegalStateException("Can not create registry " + url);
        }
        REGISTRIES.put(key, registry);
        return registry;
    } finally {
    
    
        // Release the lock
        LOCK.unlock();
    }
}

加锁来保证多线程环境下只会创建一个注册中心,有一个抽象方法createRegistry,子类来实现具体的创建过程

Zookeeper注册中心

成熟的注册中心框架,可用于生产环境

在这里插入图片描述
流程说明:

  1. 服务提供者启动时: 向 /dubbo/com.foo.BarService/providers 目录下写入自己的 URL 地址
  2. 服务消费者启动时: 订阅 /dubbo/com.foo.BarService/providers 目录下的提供者 URL 地址。并向 /dubbo/com.foo.BarService/consumers 目录下写入自己的 URL 地址
  3. 监控中心启动时: 订阅 /dubbo/com.foo.BarService 目录下的所有提供者和消费者 URL 地址。

针对每个接口节点会存在如下4个子节点(接口节点及其子节点都是持久节点)

节点名 作用 子节点是否是持久节点
configuators 存储override或者absent url,用于服务治理
consumers 服务消费者url
providers 服务提供者url
routers 设置路由url,用于服务治理

consumers节点主要是为了做监控,其他三个节点都会设置监听器,发生改变时,会触发特定事件

ZookeeperRegistry对注册中心的操作都会交给ZookeeperClient。在2.7.x版本之前,Dubbo支持zkclient和curator两种zookeeper客户端的实现,所以对zookeeper的操作又抽取出一套api出来,包括事件监听的接口。2.7.x版本只支持curator客户端

public interface ZookeeperClient {
    
    

    void create(String path, boolean ephemeral);

    void delete(String path);

    List<String> getChildren(String path);

    List<String> addChildListener(String path, ChildListener listener);

    void addDataListener(String path, DataListener listener);

    void addStateListener(StateListener listener);

}

ZookeeperClient包含了所有对注册中心的操作,并且定义了3种类型的监听器

  1. StateListener,监听连接状态
  2. ChildListener,监听获得一个节点的所有子节点(发生任何事件都重新获取一下)
  3. DataListener,监听本节点及其子节点的变化(节点增加,删除,更新等)

在这里插入图片描述
AbstractZookeeperClient主要对添加和删除监听器进行并发控制。如果已经对某个路径添加了监听器就不再添加。

CuratorZookeeperClient主要就是利用curaotr api对zookeeper进行操作的实现。其内部类CuratorWatcherImpl将curator中的事件转化为dubbo中的事件

参考博客

[1]https://zhuanlan.zhihu.com/p/97300195

猜你喜欢

转载自blog.csdn.net/zzti_erlie/article/details/109408234
今日推荐