介绍
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注册中心
成熟的注册中心框架,可用于生产环境
流程说明:
- 服务提供者启动时: 向 /dubbo/com.foo.BarService/providers 目录下写入自己的 URL 地址
- 服务消费者启动时: 订阅 /dubbo/com.foo.BarService/providers 目录下的提供者 URL 地址。并向 /dubbo/com.foo.BarService/consumers 目录下写入自己的 URL 地址
- 监控中心启动时: 订阅 /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种类型的监听器
- StateListener,监听连接状态
- ChildListener,监听获得一个节点的所有子节点(发生任何事件都重新获取一下)
- DataListener,监听本节点及其子节点的变化(节点增加,删除,更新等)
AbstractZookeeperClient主要对添加和删除监听器进行并发控制。如果已经对某个路径添加了监听器就不再添加。
CuratorZookeeperClient主要就是利用curaotr api对zookeeper进行操作的实现。其内部类CuratorWatcherImpl将curator中的事件转化为dubbo中的事件。
参考博客
[1]https://zhuanlan.zhihu.com/p/97300195