写点什么

zookeeper 集群之间如何通讯

作者:浅羽技术
  • 2022 年 9 月 30 日
    四川
  • 本文字数:3508 字

    阅读完需:约 12 分钟

zookeeper集群之间如何通讯

Zookeeper 的通信架构

在 Zookeeper 整个系统中,有 3 中角色的服务,client、Follower、leader。其中 client 负责发起应用的请求,Follower 接受 client 发起的请求,参与事务的确认过程,在 leader crash 后的 leader 选择。


而 leader 主要承担事务的协调,当然 leader 也可以承担接收客户请求的功能,为了方便描述,后面的描述都是 client 与 Follower 之间的通信,如果 Zookeeper 的配置支持 leader 接收 client 的请求,client 与 leader 的通信跟 client 与 Follower 的通信模式完全一样。


Follower 与 leader 之间的角色可能在某一时刻进行转换。一个 Follower 在 leader crash 掉以后可能被集群(Quorum)的 Follower 选举为 leader。而一个 leader 在 crash 后,再次加入集群(Quorum)将作为 Follower 角色存在。


在一个集群(Quorum)中,除了在选举 leader 的过程中没有 Follower 和 leader 的区分外,其他任何时刻都只有 1 个 leader 和多个 Follower。Client、Follower 和 leader 之间的通信架构如下:

Client 与 Follower 之间

为了使客户端具有较高的吞吐量,Client 与 Follower 之间采用 NIO 的通信方式。当 client 需要与 Zookeeper service 打交道时,首先读取配置文件确定集群内的所有 server 列表,按照一定的 load balance 算法选取一个 Follower 作为一个通信目标。


这样 client 和 Follower 之间就有了一条由 NIO 模式构成的通信通道。这条通道会一直保持到 client 关闭 session 或者因为 client 或 Follower 任一方因某种原因异常中断通信连接。正常情况下, client 与 Follower 在没有请求发起的时候都有心跳检测

Follower 与 leader 之间

Follower 与 leader 之间的通信主要是因为 Follower 接收到像(create, delete, setData, setACL, createSession, closeSession, sync)这样一些需要让 leader 来协调最终结果的命令,将会导致 Follower 与 leader 之间产生通信。


由于 leader 与 Follower 之间的关系式一对多的关系,非常适合 client/server 模式,因此他们之间是采用 c/s 模式,由 leader 创建一个 socket server,监听各 Follower 的协调请求。

集群在选择 leader 过程中

由于在选择 leader 过程中没有 leader,在集群中的任何一个成员都需要与其他所有成员进行通信,当集群的成员变得很大时,这个通信量是很大的。


选择 leader 的过程发生在 Zookeeper 系统刚刚启动或者是 leader 失去联系后,选择 leader 过程中将不能处理用户的请求,为了提高系统的可用性,一定要尽量减少这个过程的时间。选择哪种方式让他们可用快速得到选择结果呢?


Zookeeper 在这个过程中采用了策略模式,可用动态插入选择 leader 的算法。系统默认提供了 3 种选择算法,AuthFastLeaderElection,FastLeaderElection,LeaderElection。


其中 AuthFastLeaderElection 和 LeaderElection 采用 UDP 模式进行通信,而 FastLeaderElection 仍然采用 tcp/ip 模式。在 Zookeeper 新的版本中,新增了一个 learner 角色,减少选择 leader 的参与人数。使得选择过程更快。


一般说来 Zookeeper leader 的选择过程都非常快,通常<200ms。

Zookeeper 的通信流程

要详细了解 Zookeeper 的通信流程,我们首先得了解 Zookeeper 提供哪些客户端的接口,我们按照具有相同的通信流程的接口进行分组:

Zookeeper 系统管理命令

Zookeeper 的系统管理接口是指用来查看 Zookeeper 运行状态的一些命令,他们都是具有 4 字母构成的命令格式。主要包括:


ruok:发送此命令可以测试 zookeeper 是否运行正常。


dump:dump server 端所有存活 session 的 Ephemeral(临时)node 信息。


stat:获取连接 server 的服务器端的状态及连接该 server 的所有客服端的状态信息。


reqs: 获取当前客户端已经提交但还未返回的请求。


stmk:开启或关闭 Zookeeper 的 trace level.


gtmk:获取当前 Zookeeper 的 trace level 是否开启。


envi: 获取 Zookeeper 的 java 相关的环境变量。


srst:重置 server 端的统计状态


当用户发送这些命令的到 server 时,由于这些请求只与连接的 server 相关,没有业务处理逻辑,非常简单。


Zookeeper 对这些命令采用最快的效率进行处理。这些命令发送到 server 端只占用一个 4 字节的 int 类型来表示不同命令,没有采用字符串处理。当服务器端接收到这些命令,立刻返回结果。

Session 创建

任何客户端的业务请求都是基于 session 存在的前提下。Session 是维持 client 与 Follower 之间的一条通信通道,并维持他们之间从创建开始后的所有状态。


当启动一个 Zookeeper client 的时候,首先按照一定的算法查找出 follower, 然后与 Follower 建立起 NIO 连接。当连接建立好后,发送 create session 的命令,让 server 端为该连接创建一个维护该连接状态的对象 session。当 server 收到 create session 命令,先从本地的 session 列表中查找看是否已经存在有相同 sessionId,


则关闭原 session 重新创建新的 session。创建 session 的过程将需要发送到 Leader,再由 leader 通知其他 follower,大部分 Follower 都将此操作记录到本地日志再通知 leader 后,leader 发送 commit 命令给所有 Follower,


连接客户端的 Follower 返回创建成功的 session 响应。Leader 与 Follower 之间的协调过程将在后面的做详细讲解。当客户端成功创建好 session 后,其他的业务命令就可以正常处理了。

Zookeeper 查询命令

Zookeeper 查询命令主要用来查询服务器端的数据,不会更改服务器端的数据。所有的查询命令都可以即刻从 client 连接的 server 立即返回,不需要 leader 进行协调,因此查询命令得到的数据有可能是过期数据。


但由于任何数据的修改,leader 都会将更改的结果发布给所有的 Follower,因此一般说来,Follower 的数据是可以得到及时的更新。这些查询命令包括以下这些命令:


exists:判断指定 path 的 node 是否存在,如果存在则返回 true,否则返回 false.


getData:从指定 path 获取该 node 的数据


getACL:获取指定 path 的 ACL。


getChildren:获取指定 path 的 node 的所有孩子结点。


所有的查询命令都可以指定 watcher,通过它来跟踪指定 path 的数据变化。一旦指定的数据发生变化(create,delete,modified,children_changed),服务器将会发送命令来回调注册的 watcher. Watcher 详细的讲解将在 Zookeeper 的 Watcher 中单独讲解。

Zookeeper 修改命令

Zookeeper 修改命令主要是用来修改节点数据或结构,或者权限信息。任何修改命令都需要提交到 leader 进行协调,协调完成后才返回。修改命令主要包括:


1 . createSession:请求 server 创建一个 session


2 . create:创建一个节点


3 . delete:删除一个节点


4 . setData:修改一个节点的数据


5 . setACL:修改一个节点的 ACL


6 . closeSession:请求 server 关闭 session


我们根据前面的通信图知道,任何修改命令都需要 leader 协调。 在 leader 的协调过程中,需要 3 次 leader 与 Follower 之间的来回请求响应。并且在此过程中还会涉及事务日志的记录,更糟糕的情况是还有 take snapshot 的操作。因此此过程可能比较耗时。但 Zookeeper 的通信中最大特点是异步的,如果请求是连续不断的,Zookeeper 的处理是集中处理逻辑,然后批量发送,批量的大小也是有控制的。如果请求量不大,则即刻发送。这样当负载很大时也能保证很大的吞吐量,时效性也在一定程度上进行了保证。

zookeeper server 端的业务处理-processor 链


Zookeeper 通过链式的 processor 来处理业务请求,每个 processor 负责处理特定的功能。不同的 Zookeeper 角色的服务器 processor 链是不一样的,以下分别介绍 standalone Zookeeper server, leader 和 Follower 不同的 processor 链。

Zookeeper 中的 processor

AckRequestProcessor:当 leader 从向 Follower 发送 proposal 后,Follower 将发送一个 Ack 响应,leader 收到 Ack 响应后,将会调用这个 Processor 进行处理。它主要负责检查请求是否已经达到了多数 Follower 的确认,如果满足条件,则提交 commitProcessor 进行 commit 处理


CommitProcessor:从 commited 队列中处理已经由 leader 协调好并 commit 的请求或者从请求队列中取出那些无需 leader 协调的请求进行下一步处理。


FinalRequestProcessor:任何请求的处理都需要经过这个 processor,这是请求处理的最后一个 Processor,主要负责根据不同的请求包装不同的类型的响应包。当然 Follower 与 leader 之间协调后的请求由于没有 client 连接,将不需要发送响应(代码体现在 if (request.cnxn == null) {return;})。


FollowerRequestProcessor:Follower processor 链上的第一个,主要负责将修改请求和同步请求发往 leader 进行协调。


PrepRequestProcessor:在 leader 和 standalone server 上作为第一 Processor,主要作用对于所有的修改命令生成 changelog。


ProposalRequestProcessor:leader 用来将请求包装为 proposal 向 Follower 请求确认。


SendAckRequestProcessor:Follower 用来向 leader 发送 Ack 响应的处理。


SyncRequestProcessor:负责将已经 commit 的事务写到事务日志以及 take snapshot.


ToBeAppliedRequestProcessor:负责将 tobeApplied 队列的中 request 转移到下一个请求进行处理。

发布于: 刚刚阅读数: 4
用户头像

浅羽技术

关注

才疏学浅,习习而为,编程羽录,与你同行。 2019.02.26 加入

分享一些计算机信息知识、理论技术、工具资源、软件介绍、后端开发、面试、工作感想以及生活随想等一系列文章。

评论

发布
暂无评论
zookeeper集群之间如何通讯_zookeeper_浅羽技术_InfoQ写作社区