Dubbo注册中心(二)—— 订阅/发布

订阅/发布是整个注册中心的核心功能之一


当一个已有服务提供者节点下线, 或者一个新的服务提供者节点加入微服务环境时, 订阅对应接口的消费者和服务治理中心都能及时收到注册中心的通知, 并更新本地的配置信息。 如此一来, 后续的服务调用就能避免调用已经下线的节点, 或者能调用到新的节点。 整个过程都是自动完成的, 不需要人工参与。Dubbo在上层抽象了这样一个工作流程, 但可以有不同的实现。 本章主要讲解ZooKeeper和Redis的实现方式。

ZooKeeper 的实现


1、发布的实现
服务提供者和消费者都需要把自己注册到注册中心。 服务提供者的注册是为了让消费者感知服务的存在, 从而发起远程调用; 也让服务治理中心感知有新的服务提供者上线。 消费者的发布是为了让服务治理中心可以发现自己。 ZooKeeper发布代码非常简单, 只是调用了ZooKeeper的客户端库在注册中心上创建一个目录,代码如下所示:

代码清单 zkClient创建目录源码

zkClient.create(toUrlPath(url)
url.getParameter(Constants.DYNAMIJKEY, true));

取消发布也很简单, 只是把ZooKeeper注册中心上对应的路径删除,代码如下所示:

代码清单 zkClient删除路径源码

zkClient.delete(toUrlPath(url));

2、订阅的实现
订阅通常有pull和push两种方式, 一种是客户端定时轮询注册中心拉取配置, 另一种是注册中心主动推送数据给客户端。 这两种方式各有利弊, 目前Dubbo采用的是第一次启动拉取方式, 后续接收事件重新拉取数据。
在服务暴露时, 服务端会订阅configurators用于监听动态配置, 在消费端启动时, 消费端会订阅providers、 routers和configuratops这三个目录, 分别对应服务提供者、 路由和动态配置变更通知
3、Dubbo中有哪些ZooKeeper客户端实现?
无论服务提供者还是消费者, 或者是服务治理中心, 任何一个节点连接到ZooKeeper注册中心都需要使用一个客户端, Dubbo在dubbo-remoting-zookeeper模块中实现了 ZooKeeper客户端的统一封装, 定义了统一的Client API,并用两种不同的ZooKeeper开源客户端库实现了这个接口:
• Apache Curator;
• zkCliento
用户可以在<dubbo: registry>的client属性中设置curator、 zkclient来使用不同的客户端实现库, 如果不设置则默认使用Curator作为实现
ZooKeeper注册中心采用的是“事件通知” + “客户端拉取” 的方式, 客户端在第一次连接上注册中心时, 会获取对应目录下全量的数据。 并在订阅的节点上注册一个watcher,客户端与注册中心之间保持TCP长连接, 后续每个节点有任何数据变化的时候, 注册中心会根据watcher的回调主动通知客户端(事件通知) , 客户端接到通知后, 会把对应节点下的全量数据都拉取过来(客户端拉取) , 这一点在NotifyListener#notify(List urls)接口上就有约束的注释说明。 全量拉取有一个局限, 当微服务节点较多时会对网络造成很大的压力。ZooKeeper的每个节点都有一个版本号, 当某个节点的数据发生变化(即事务操作) 时,该节点对应的版本号就会发生变化, 并触发watcher事件, 推送数据给订阅方。 版本号强调的是变更次数, 即使该节点的值没有变化, 只要有更新操作, 依然会使版本号变化

Redis 的实现

1 .总体流程
使用Redis作为注册中心, 其订阅发布实现方式与ZooKeeper不同。 我们在Redis注册中心的数据结构中已经了解到, Redis订阅发布使用的是过期机制和publish/subscribe通道。 服务提供者发布服务, 首先会在Redis中创建一个key,然后在通道中发布一条register事件消息。但服务的key写入Redis后, 发布者需要周期性地刷新key过期时间, 在RedisRegistry构造方法中会启动一个expireExecutor定时调度线程池, 不断调用deferExpired()方法去延续key的超时时间。 如果服务提供者服务宕机, 没有续期, 则key会因为超时而被Redis删除, 服务也就会被认定为下线

整个Redis注册中心的工作流程, 如下图所示
Dubbo注册中心(二)—— 订阅/发布_第1张图片

 

 

 

你可能感兴趣的:(深入理解Apache,Dubbo,java,zookeeper,dubbo,rpc)