background image

下面我们分别以

leader 和 follower 的角度看下 server 接下来的行为。在这之前需要对

ZookeeperServer 的处理器链有一个了解。单机版 Server、Leader、Follower、Observer 分别对应
ZooKeeperServer、LeaderZooKeeperServer、FollowerZooKeeperServer、ObserverZooKeeperServ
er。4 种 Server 共享 Processor 处理器,各自将某几个 Processor 按顺序组合为一个 Processor
链。在每个

Server 中请求总是从第一个 Processor 开始处理,处理完交给下一个,直到走完

整个

Processor 链。4 种 Server 的 Processor 链组合如下图所示:

zookeeper-3.3.1-processor-chain

Leader

QuorumPeer 线程确定自己是 Leader 后,调用 Leader 对象的 lead 方法。lead 方法首先通过

LeaderZooKeeperServer 的 setupRequestProcessors 方法初始化处理器链,启动 3 个 processors
线程:

1. PrepRequestProcessor 线程。该线程消费请求队列 submittedRequests,开始实施一致性算法。
submittedRequests 有两个来源,一是接入的客户端直接提交,提交的请求既包括写请求,
也包括一些查询请求;另一个是由

Follower 转发,转发内容只包括写请求和同步请求 。

PrepRequestProcessor 收到 submittedRequest 后,将请求转发给 CommitProcessor 线程和
SyncRequestProcessor 线程的输入队列;对于其中的写请求,向所有 follower 发送
PROPOSAL 消息(异步发送)。

2. CommitProcessor 线程。该线程主要消费两个队列 queuedRequests 和
committedRequests。queuedRequests 保存 PrepRequestProcessor 线程下发的 submittedRequest
消息。

committedRequests 保存 Proposal 通过后,LearnerHanlder 线程(后文会有说明)发来

的提交请求。

CommitProcessor 在这里做了如下处理:对于 queuedRequests 中客户端的查询

request,直接返回本地数据;对于客户端提交的或 follower 转发来的写请求,作为一个
pendingRequest 等待相应的表决结果返回 committedRequest 到 committedRequests 队列。对于
队列中到来的每一个

committedRequest,如果当前有 pendingRequest 等待,并且其

sessionId,zxid 和这个请求匹配,则处理 pendingRequest(如果原始请求发自客户端,
pendingRequest 会携带客户端连接对象,从而能够发送响应给客户端),否则直接处理
committedRequest(这种情况对应 Follower 中的 CommitProcessor 直接接收到了 commit 消
息)。处理的过程是记录

committedLog,变更本地数据。如果请求从客户端来,发送响应给

客户端。那么如果一个

pendingRequest 始终等不到对应的 committedRequest 到来呢?答案是