专栏首页服务端思维如何使用Zookeeper实现服务注册中心

如何使用Zookeeper实现服务注册中心

一个完整的服务注册中心一般包括服务注册与服务发现两部分,涉及服务提供者、服务注册中心、服务消费者三种角色。其中服务提供者主要负责将自身的服务信息注册到服务注册中心。服务注册中心主要提供所有服务注册信息的中心存储,同时负责将服务注册信息的更新通知实时的Push给服务消费者。服务消费者负责从服务注册中心获取需要的服务注册信息,并缓存在本地。

构建发布/订阅机制是实现注册中心的关键。虽然,通过观察者模式,我们也可以实现发布/订阅机制的基本功能,但考虑到注册中心对数据一致性、可用性的要求,选择一种在复杂网络环境下具备分布式协调功能的中间件系统,可能是最佳方案。

Zookeeper是目前实现该功能的主流方案,按照官方的说法,它不仅天生支持分布式,同时通过Watcher机制,客户端还可以监听节点的数据变更和子节点变更。如下是Zookeeper的结构图:

从图中我们可以看到,它与Unix文件系统很类似,是一个树状层次结构。其中的每个节点叫做Znode,节点既可以拥有子节点,也可以允许将少量数据存储在该节点下。

Zookeeper如何实现发布/订阅

Zookeeper实现发布/订阅是利用Watcher机制,Watcher实现由三个部分组成:

  • Zookeeper服务端;
  • Zookeeper客户端;
  • 客户端的ZKWatchManager对象;

客户端首先将Watcher注册到Zookeeper服务端,同时将Watcher对象保存到客户端的Watch管理器中。当ZooKeeper服务端监听的数据状态发生变化时,服务端会主动通知Zookeeper客户端,接着客户端的Watch管理器会触发相关Watcher来回调相应处理逻辑,从而完成整体的数据发布/订阅流程。如上图所示。

Watcher特性

Watcher接口设计

Watcher是一个接口,任何实现了Watcher接口的类就是一个新的Watcher。Watcher内部包含了两个枚举类:KeeperState、EventType。

Watcher通知状态(KeeperState)

KeeperState是客户端与服务端连接状态发生变化时对应的通知类型。路径为org.apache.zookeeper.Watcher.Event.KeeperState,是一个枚举类,其枚举属性如下:

Watcher事件类型(EventType)

EventType是数据节点(znode)发生变化时对应的通知类型。EventType变化时KeeperState永远处于SyncConnected通知状态下;

当KeeperState发生变化时EventType永远为None。其路径为org.apache.zookeeper.Watcher.Event.EventType,是一个枚举类,枚举属性如下:

:客户端接收到的相关事件通知中只包含状态及类型等信息,不包括节点变化前后的具体内容,变化前的数据需业务自身存储,变化后的数据需调用get等方法重新获取;

Watcher注册及通知流程

客户端Watcher管理器:ZKWatchManager数据结构

服务端Watcher管理器:WatchManager数据结构

Watcher注册流程

Watcher通知流程

Zookeeper如何保证数据的一致性

在集群环境中,Zookeeper能保证数据一致性,要归功于ZAB协议。ZAB协议是Zookeeper用来实现数据一致性的算法,它包含了两个可以无限重复的阶段:

第一个阶段是领导者选举阶段,此阶段集群中所有的机器通过一个选举过程来选择出一台被称为领导者的机器,而其他的机器被称为跟随者。当一旦半数以上的跟随者已经将其状态与领导者同步,则表明整个阶段已经完成。

第二个阶段是原子广播阶段,在此阶段,所有的写操作都首先会被转发给领导者,然后再由领导者通过广播更新至跟随者。当半数以上的跟随者已经将修改持久化后,领导者才会提交整个更新,然后客户端才会收到一个更新成功的响应。这个用来达成共识的写操作具有原子性,要么成功,或者要么失败。在集群运行过程中,如果领导者出现故障,其余的机器会选举出一个新的领导者,并与新的领导者一起继续提供服务。后面如果之前的领导者恢复正常,那它会成为一个跟随者。

从概念上讲,ZAB协议所做的就是确保对节点的每一个写操作都会被复制到集群中超过半数的机器上。如果少于半数的机器出现故障,则至少有一台机器会保存最新的状态,并且其余副本最终也会更新到这个状态。领导者选举用于服务启动或者领导者崩溃的场景,而原子广播则对每个更新操作进行结果状态同步。

Zab 协议中的 Zxid

Zookeeper中的每一个节点的更新都被赋予一个全局唯一的ID,称为Zookeeper事务Id,也即是Zxid。Zxid具备全局递增性,它决定了分布式环境下更新操作的执行顺序。例如,如果Zxid a < Zxid b,那a一定发生在b之前。创建、更新、删除任意节点都会导致Zookeeper状态发生改变,并且最终导致Zxid的值的增加。

Zookeeper节点类型

Zookeeper中的节点有临时节点和持久节点之分,临时节点的生命周期很短,通常会话结束后,Zookeeper就会删除该节点。而持久节点不依赖与客户端的会话,只有当客户端明确要求删除该持久节点时,该节点才会被删除。ZNode的这种特性可以用于控制该节点代表的服务定义元数据的时效性。

Zookeeper中每一个会话都有一个超时的时间设置,如果服务器在超时时间段内没有收到任何请求,则相应的会话会过期。一旦一个会话已经过期,就无法重新被打开,并且任何与该会话相关联的临时节点都会丢失。要保证一个会话不过期,可以让客户端定时向服务端发送心跳请求,以保证连接的活跃性。

当服务器发生故障时,Zookeeper客户端可以自动切换到另一台Zookeeper服务器,并且关键的是在另一台服务器接替故障服务器之后,所有的会话仍然有效。会话的超时时间、心跳和自动故障切换机制确保了Zookeeper服务的可靠性。

Zookeeper正是通过这些特征来实现注册中心,以及保证注册中心的高可用和数据一致性。

本文分享自微信公众号 - 服务端思维(gh_c3775931ac9d)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-09-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • GitHub标星1w+超牛的微服务项目,开发脚手架

    Cloud-Platform是国内首个基于Spring Cloud微服务化开发平台,具有统一授权、认证后台管理系统,其中包含具备用户管理、资源权限管理、网关AP...

    用户2781897
  • 原来这就是RPC呀,也没那么难嘛?

    RPC就是远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的思想。

    用户2781897
  • Redis中string、list的底层数据结构原理

    Redis 有一个比较突出的特点就是数据结构更丰富, 「string、hash、list、set、zset、Redis5.0 新数据结构-stream」

    用户2781897
  • 单机数据库的实现(下)

    文件事件处理器使用I/O多路复用的程序来同时监听多个套接字,虽然redis的文件事件处理器以单线程方式运行,但通过io多路复用监听多个套接字,这样实现了高性能的...

    用户7962184
  • SignalR使用笔记

    2) 默认情况下,这是IPrincipal.Identity.Name,但是可以通过向全局主机注册IUserIdProvider的实现来更改。

    用户6362579
  • ES10新特性(一)

    BigInt 是一个任意精度的整数。这意味着变量现在可以 表示²⁵³ 数字,而不仅仅是9007199254740992。

    ConardLi
  • 这本4分+百年期刊去年被剔除SCI,今年重回SCI,影响因子还涨了!

    去年9月份,网传一本拥有100多年历史的4分百年名刊Annals of the New York Academy of Sciences被剔除SCI。

    百味科研芝士
  • 浅谈RSA加密算法

    听着music睡
  • 新加坡研制出机器人图书馆员

    虽然资料的即时访问与下载是数字时代的一个标志,但世界上有许多知识仍以书籍的形式保存,卷宗跟踪是一项既枯燥又耗体力的工作。如今新加坡科技研究局(A*STAR)开发...

    人工智能快报
  • OpenStack命令创建网络

    [root@controller ~]# neutron net-create provider-666 neutron CLI is deprecated a...

    院长技术

扫码关注云+社区

领取腾讯云代金券