Leader服务器是整个ZooKeeper集群工作机制中的核心,其主要工作有以下两个。
事务请求的唯一调度和处理者,保证集群事务处理的顺序性。
集群内部各服务器的调度者。
请求处理链
使用责任链模式来处理每一个客户端请求是ZooKeeper的一大特色。在每一个服务器启动的时候,都会进行请求处理链的初始化,Leader服务器的请求处理链如下图所示。
从上图中可以看到,从PrepRequestProcessor到FinalRequestProcessor,前后一共7个请求处理器组成了Leader服务器的请求处理链。
PrepRequestProcessor
PrepRequestProcessor是Leader服务器的请求预处理器,也是Leader 服务器的第一个请求处理器。在ZooKeeper中,我们将那些会改变服务器状态的请求称为“事务请求”一通常指的就是那些创建节点、更新数据、删除节点以及创建会话等请求,PrepRequestProcessor能够识别出当前客户端请求是否是事务请求。对于事务请求,PrepRequestProcessor处理器会对其进行一系列预处理,诸如创建请求事务头、事务体,会话检查、ACL检查和版本检查等。
ProposalRequestProcessor
ProposalRequestProcessor处理器是Leader服务器的事务投票处理器,也是Leader服务器事务处理流程的发起者。对于非事务请求,ProposalRequestProcessor会直接将请求流转到CommitProcessor处理器,不再做其他处理;而对于事务请求,除了将请求交给CommitProcessor处理器外,还会根据请求类型创建对应的Proposal提议,并发送给所有的Followver 服务器来发起一次集群内的事务投票。同时,ProposalRequestProcessor还会将事务请求交付给SyncRequestProcessor进行事务日志的记录。
SyncRequestProcessor
SyncRequestProcessor是事务日志记录处理器,该处理器主要用来将事务请求记录到事务日志文件中去,同时还会触发ZooKeeper进行数据快照。
AckRequestProcessor
AckRequestProcessor处理器是Leader特有的处理器,其主要负责在SyncRequestProcessor处理器完成事务日志记录后,向Proposal的投票收集器发送ACK反馈,以通知投票收集器当前服务器已经完成了对该Proposal的事务日志记录。
CommitProcessor
CommitProcessor是事务提交处理器。对于非事务请求,该处理器会直接将其交付给下一级处理器进行处理;而对于事务请求,CommitProcessor处理器会等待集群内针对Proposal的投票直到该Proposal可被提交。利用CommitProcessor处理器,每个服务器都可以很好地控制对事务请求的顺序处理。
ToBeCommitProcessor
ToBeCommitProcessor是一个比较特别的处理器,根据其命名,相信读者也已经理解了该处理器的作用。ToBeCommitProcessor处理器中有一个toBeApplied队列,专门用来存储那些已经被CommitProcessor处理过的可被提交的Proposal。
ToBeCommitProcessor处理器将这些请求逐个交付给FinalRequestProcessor处理器进行处理——等到FinalRequestProcessor 处理器处理完之后,再将其从toBeApplied队列中移除。
FinalRequestProcessor
FinalRequestProcessor是最后一个请求处理器。该处理器主要用来进行客户端请求返回之前的收尾工作,包括创建客户端请求的响应;针对事务请求,该处理器还会负责将事务应用到内存数据库中去。
LearnerHandler
为了保持整个集群内部的实时通信,同时也是为了确保可以控制所有的Follower/Observer服务器,Leader服务器会与每一个Follower/Observer 服务器都建立一个TCP长连接,同时也会为每个Follower/Observer服务器都创建一个名为LearnerHandler的实体。
LearnerHandler,顾名思义,是ZooKeeper集群中Learner服务器的管理器,主要负责Follower/Observer服务器和Leader服务器之间的一系列网络通信,包括数据同步、请求转发和Proposal提议的投票等。Leader服务器中保存了所有Follower/Observer对应的LearnerHandler。
从角色名字上可以看出,Follower服务器是ZooKeeper集群状态的跟随者,其主要工作
有以下三个。
处理客户端非事务请求,转发事务请求给Leader服务器。
参与事务请求Proposal的投票。
参与Leader选举投票。
和Leader服务器一样,Follower也同样使用了采用责任链模式组装的请求处理链来处理每一个客户端请求,由于不需要负责对事务请求的投票处理,因此相对来说Follower服务器的请求处理链会简单一些,其请求处理链如下图所示。
从上图中可以看到,和Leader服务器的请求处理链最大的不同点在于,Follower服务器的第一个处理器换成了FollowerRequestProcessor处理器,同时由于不需要处理事务请求的投票,因此也没有了ProposalRequestProcessor处理器。
FollowerRequestProcessor
FollowerRequestProcessor是Follower 服务器的第一个请求处理器,其主要工作就是识别出当前请求是否是事务请求。如果是事务请求,那么Follower就会将该事务请求转发给Leader 服务器,Leader服务器在接收到这个事务请求后,就会将其提交到请求处理链,按照正常事务请求进行处理。
SendAckRequestProcessor
SendAckRequestProcessor是Follower服务器上另外一个和Leader服务器有差异的请求处理器。Leader服务器上有一个叫AckRequestProcessor的请求处理器,其主要负责在SyncRequestProcessor处理器完成事务日志记录后,向Proposal的投票收集器进行反馈。而在Follower服务器上,SendAckRequestProcessor处理器同样承担了事务日志记录反馈的角色,在完成事务日志记录后,会向Leader服务器发送ACK消息以表明自身完成了事务日志的记录工作。两者的唯一区别在于,AckRequestProcessor 处理器和Leader服务器在同一个服务器上,因此它的ACK反馈仅仅是一个本地操作;而SendAckRequestProcessor处理器由于在Follower服务器上,因此需要通过以ACK消息的形式来向Leader服务器进行反馈。
Observer是ZooKeeper自3.3.0 版本开始引入的一个全新的服务器角色。从字面意思看,该服务器充当了一个观察者的角色——其观察ZooKeeper集群的最新状态变化并将这些状态变更同步过来。Observer服务器在工作原理上和Follower基本是一致的,对于非事务请求,都可以进行独立的处理,而对于事务请求,则会转发给Leader服务器进行处理。
和Follower唯一的区别在于,Observer不参与任何形式的投票,包括事务请求Proposal的投票和Leader选举投票。简单地讲,Observer 服务器只提供非事务服务,通常用于在不影响集群事务处理能力的前提下提升集群的非事务处理能力。
另外,Observer的请求处理链路和Follower服务器也非常相近,如下图所示。
另外需要注意的一点是,虽然在上图中,Observer服务器在初始化阶段会将SyncRequestProcessor处理器也组装上去,但是在实际运行过程中,Leader服务器不会将事务请求的投票发送给Observer服务器。
在整个ZooKeeper集群工作过程中,都是由Leader服务器来负责进行各服务器之间的协调,同时,各服务器之间的网络通信,都是通过不同类型的消息传递来实现的。在本节中,我们将围绕ZooKeeper集群间的消息通信来讲解ZooKeeper集群各服务器之间是如何进行协调的。
ZooKeeper的消息类型大体上可以分为四类,分别是:数据同步型、服务器初始化型、请求处理型和会话管理型。
数据同步型
数据同步型消息是指在Learner和Leader服务器进行数据同步的时候,网络通信所用到的消息,通常有DIFF、TRUNC、SNAP和UPTODATE四种。下表中分别对这四种消息类型进行了详细介绍。
消息类型 |
发送方-->接收方 |
说明 |
DIFF,13 |
Leader-->Learner |
用于通知Learner服务器,Leader即将与其进行“DIFF”方式的数据同步 |
TRUNC,14 |
Leader-->Learner |
用于触发Learner服务器进行内存数据库的回滚操作 |
SNAP,15 |
Leader-->Learner |
用于通知Learner服务器,Leader 即将与其进行“全量”方式的数据同步 |
UPTODATE,12 |
Leader-->Learner |
用来告诉Learner服务器,已经完成了数据同步,可以开始对外提供服务了 |
服务器初始化型
服务器初始化型消息是指在整个集群或是某些新机器初始化的时候,Leader和Learner之间相互通信所使用的消息类型,常见的有OBSERVERINFO、FOLLOWERINFO.LEADERINFO、ACKEPOCH和NEWLEADER五种。下表中对这五种消息类型进行了详细介绍。
消息类型 |
发送方-->接收方 |
说明 |
OBSERVERINFO,16 |
Observer-->Leader |
该信息通常是由Observer服务器在启动的时候发送 给Leader的,用于向Leader服务器注册自己,同时向Leader服务器表明当前Learner服务器的角色是Observer。消息中包含了当前Observer服务器的SID和已经处理的最新ZXID |
FOLLOWERINFO,11 |
Follower-->Leader |
该信息通常是由Follower服务器在启动的时候发送 给Leader的,用于向Leader服务器注册自己,同时向Leader服务器表明当前Learner服务器的角色是Follower。消息中包含了当前Follower服务器的SID和已经处理的最新ZXID |
LEADERINFO,17 |
Leader-->Learner |
在上面我们已经提到,在Learner连接上Leader后, 会向Leader发送LearnerInfo消息(包含了OBSERVE RINFO和FOLLOWERINFO两类消息),Leader服务 器在接收到该消息后,也会将Leader服务器的基本信息发送给这些Learner,这个消息就是LEADERINFO,通常包含了当前Leader服务器的最新EPOCH值 |
ACKEPOCH,18 |
Learner-->Leader |
Learner在接收到Leader发来的LEADERINFO消息 后,会将自己最新的ZXID和EPOCH以ACKEPOCH 消息的形式发送给Leader |
NEWLEADER,10 |
Leader-->Learner |
该消息通常用于Leader服务器向Learner发送一个 阶段性的标识消息一Leader 会在和Learner完成一 个交互流程后,向Learner发送NEWLEADER消息, 同时带上当前Leader服务器处理的最新ZXID。这一 系列交互流程包括:足够多的Follower服务器连接上Leader或是完成数据同步 |
请求处理型
请求处理型消息是指在进行请求处理的过程中,Leader和Learner服务器之间互相通信所使用的消息,常见的有REQUEST、PROPOSAL、ACK、COMMIT、INFORM和SYNC六种下表中对这六种消息类型进行了详细介绍。
消息类型 |
发送方-->接收方 |
说明 |
REQUEST,1 |
Learner-->Leader |
该消息是ZooKeeper的请求转发消息。在ZooKeeper中,所有的事务请求必须由Leader服务器来处理。当Learner服务器接收到客户端的事务请求后,就会将请求以REQUEST消息的形式转发给Leader服务器来处理 |
PROPOSAL,2 |
Leader-->Follower |
该消息是ZooKeeper实现ZAB算法的核心所在,即ZAB协议中的提议。在处理事务请求的时候,Leader服务器会将事务请求以PROPOSAL消息的形式创建投票发送给集群中所有的Follower服务器来进行事务日志的记录 |
ACK,3 |
Follower-->Leader |
Follower服务器在接收到来自Leader 的PROPOSAL消息后,会进行事务日志的记录。如果完成了事务日志的记录那么就会以ACK消息的形式反馈给Leader |
COMMIT,4 |
Leader-->Follower |
该消息用于通知集群中所有的Follower服务器,可以进行事务请求的提交了。Leader服务器在接收到过半的Follower服务器发来的ACK消息后,就进入事务请求的最终提交流程一生成COMMIT消息,告知所有的Follower服务器进行事务请求的提交 |
INFORM,8 |
Leader-->Observer |
在事务请求提交阶段,针对Follower服务器,Leader 仅仅只需要发送一个COMMIT消息,Follower 服务器就可以完成事务请求的提交了,因为在这之前的事务请求投票阶段,Follower已经接收过PROPOSAL消息,该消息中包含了事务请求的内容,因此Follower可以从之前的Proposal缓存中再次获取到事务请求。而对于Observer来说,由于之前没有参与事务请求的投票,因此没有该事务请求的上下文,显然,如果Leader同样对其发送一个简单的COMMIT消息,Observer服务器是无法完成事务请求的提交的。为了解决这个问题,ZooKeeper 特别设计了INFORM消息,该消息不仅能够通知Observer已经可以提交事务请求,同时还会在消息中携带事务请求的内容 |
SYNC,7 |
Leader-->Learner |
该消息用于通知Learner服务器已经完成了Sync操作 |
会话管理型
会话管理型消息是指ZooKeeper在进行会话管理的过程中,和Learner服务器之间互相通信所使用的消息,常见的有PING和REVALIDATE两种。下表中对这两种消息类型进行了详细的介绍。
消息类型 |
发送方-->接收方 |
说明 |
PING,5 |
Leader-->Learner |
该消息用于Leader同步Learner 服务器上的客户端心跳检测,用以激活存活的客户端。ZooKeeper 的客户端往往会随机地和任意一个ZooKeeper服务器保持连接,因此Leader服务器无法直接接收到所有客户端的心跳检测,需要委托给Learner来保存这些客户端的心跳检测记录。Leader会定时地向Learner服务器发送PING消息,Learner服务器在接收到PING消息后,会将这段时间内保持心跳检测的客户端列表,同样以PING消息的形式反馈给Leader服务器,由Leader服务器来负责逐个对这些客户端进行会话激活 |
REVALIDATE,6 |
Learner-->Leader |
该消息用于Learner校验会话是否有效,同时也会激活会话。这通常发生在客户端重连的过程中,新的服务器需要向Leader发送REVALIDATE消息以确定该会话是否已经超时 |