Dubbo-注册中心

本章主要内容:
• 注册中心的工作流程;
• 注册中心的数据结构;
• 订阅发布的实现;
• 缓存机制;
• 重试机制;
• 设计模式。


.1注册中心概述
在Dubbo微服务体系中, 注册中心是其核心组件之一。 Dubbo通过注册中心实现了分布式环境中各服务之间的注册与发现, 是各个分布式节点之间的纽带。其中ZooKeeper是官方推荐的注册中心, 在生产环境中有过实际使用, 具体的实现在Dubbo源码的dubbo-registry-zookeeper模块中。
.1.1工作流程
注册中心的总体流程如图3-1所示。
• 服务提供者启动时, 会向注册中心写入自己的元数据信息, 同时会订阅配置元数据信息。
• 消费者启动时, 也会向注册中心写入自己的元数据信息, 并订阅服务提供者、 路由和
配置元数据信息。
• 服务治理中心(dubbo-admin)启动时, 会同时订阅所有消费者、 服务提供者、 路由和
配置元数据信息。
• 当有服务提供者离开或有新的服务提供者加入时, 注册中心服务提供者目录会发生变
化, 变化信息会动态通知给消费者、 服务治理中心。
• 当消费方发起服务调用时,会异步将调用、 统计信息等上报给监控中心(dubbo-monitor・simple)。

1.3 ZooKeeper 原理概述
ZooKeeper是树形结构的注册中心, 每个节点的类型分为持久节点、 持久顺序节点、 临时
节点和临时顺序节点。
• 持久节点: 服务注册后保证节点不会丢失, 注册中心重启也会存在。
• 持久顺序节点: 在持久节点特性的基础上增加了节点先后顺序的能力。
• 临时节点: 服务注册后连接丢失或session超时, 注册的节点会自动被移除。
• 临时顺序节点: 在临时节点特性的基础上增加了节点先后顺序的能力。
Dubbo使用ZooKeeper作为注册中心时, 只会创建持久节点和临时节点两种, 对创建的顺
序并没有要求。
2.订阅/发布
订阅/发布是整个注册中心的核心功能之一。 在传统应用系统中, 我们通常会把配置信息写入一个配置文件, 当配置需要变更时会修改配置文件,再通过手动触发内存中的配置重新加载,如重启服务等。 在集群规模较小的场景下, 这种方式也能方便地进行运维。 当服务节点数量不断上升的时候, 这种管理方式的弊端就会凸显出来。

如果我们使用了注册中心, 那么上述的问题就会迎刃而解。 当一个已有服务提供者节点下线, 或者一个新的服务提供者节点加入微服务环境时, 订阅对应接口的消费者和服务治理中心都能及时收到注册中心的通知, 并更新本地的配置信息。 如此一来, 后续的服务调用就能避免调用已经下线的节点, 或者能调用到新的节点。 整个过程都是自动完成的, 不需要人工参与。
Dubbo在上层抽象了这样一个工作流程, 但可以有不同的实现。 本章主要讲解ZooKeeper的实现方式。
2.1 ZooKeeper 的实现
1.发布的实现
服务提供者和消费者都需要把自己注册到注册中心。 服务提供者的注册是为了让消费者感知服务的存在, 从而发起远程调用; 也让服务治理中心感知有新的服务提供者上线。 消费者的发布是为了让服务治理中心可以发现自己。 
取消发布也很简单, 只是把ZooKeeper注册中心上对应的路径删除
2.订阅的实现
订阅通常有pull和push两种方式, 一种是客户端定时轮询注册中心拉取配置, 另一种是注册中心主动推送数据给客户端。 这两种方式各有利弊, 目前Dubbo采用的是第一次启动拉取方式, 后续接收事件重新拉取数据。
在服务暴露时, 服务端会订阅configurators用于监听动态配置, 在消费端启动时, 消费端会订阅providers、 routers和configuratops这三个目录, 分别对应服务提供者、 路由和动态配置变更通知。

3缓存机制
缓存的存在就是用空间换取时间, 如果每次远程调用都要先从注册中心获取一次可调用的
服务列表, 则会让注册中心承受巨大的流量压力。 另外, 每次额外的网络请求也会让整个系统
的性能下降。 因此Dubbo的注册中心实现了通用的缓存机制, 在抽象类AbstractRegistry中
实现。 AbstractRegistry类结构关系如图3-5所示。

消费者或服务治理中心获取注册信息后会做本地缓存。 内存中会有一份, 保存在Properties对象里, 磁盘上也会持久化一份文件, 通过file对象引用。
3.1缓存的加载
在服务初始化的时候, AbstractRegistry构造函数里会从本地磁盘文件中把持久化的注册数据读到Properties对象里, 并加载到内存缓存中
3.2缓存的保存与更新
缓存的保存有同步和异步两种方式。 异步会使用线程池异步保存, 如果线程在执行过程中出现异常, 则会再次调用线程池不断重试
 

5设计模式
5.1模板模式
整个注册中心的逻辑部分使用了模板模式, 其类的关系如图3-6所示。

AbstractRegistry实现了 Registry接口中的注册、 订阅、 查询、 通知等方法, 还实现了磁盘文件持久化注册信息这一通用方法。 但是注册、 订阅、 查询、 通知等方法只是简单地把URL加入对应的集合, 没有具体的注册或订阅逻辑
FailbackRegistry又继承了 AbstractRegistry,重写了父类的注册、 订阅、 查询和通知等方法, 并且添加了重试机制。 此外, 还添加了四个未实现的抽象模板方法
以订阅为例, FailbackRegistry重写了 subscribe方法, 但只实现了订阅的大体逻辑及异常处理等通用性的东西。 具体如何订阅, 交给继承的子类实现。 这就是模板模式的具体实现
5.2工厂模式
所有的注册中心实现, 都是通过对应的工厂创建的。 工厂类之间的关系如图3.7所示。

AbstractRegistryFactory 实现了 RegistryFactory 接口的 getRegistry(URL url)方法, 是一个通用实现, 主要完成了加锁, 以及调用抽象模板方法createRegistry(URL url)创建具体实现等操作, 并缓存在内存中。 抽象模板方法会由具体子类继承并实现
虽然每种注册中心都有自己具体的工厂类, 但是在什么地方判断, 应该调用哪个工厂类实现呢? 代码中并没有看到显式的判断。 答案就在RegistryFactory接口中, 该接口里有一个Registry getRegistry(URL url)方法, 该方法上有@Adaptive({"protocol"))注解, 如代码清单3-16所示

代码清单 3-16 RegistryFactory 源码
@SPI("dubbo")
public interface RegistryFactory (
@Adaptive({"protocol"})
Registry getRegistry(URL url);
)

了解AOP的读者就会很容易理解, 这个注解会自动生成代码实现一些逻辑, 它的value参数会从URL中获取protocol键的值, 并根据获取的值来调用不同的工厂类。 例如, 当url.protocol = redis时, 获得RedisRegistryFactory实现类。
 

备注:文章参考《深入理解Apache Dubbo与实战》,作者:林琳,诣极

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值