follower收到请求之后,先请求请求的opCode类型(这里是create)构造对应的request,然后交给第一个processor执行,follower的第一个processor是FollowerRequestProcessor.
follower转发请求给leader由于在zk中follower是不能处理写请求的,需要转交给leader处理,在FollowerRequestProcessor中将请求转发给leader,转发请求的调用堆栈是
serialize(OutputArchive, String):82, QuorumPacket (org.apache.zookeeper.server.quorum), QuorumPacket.java writeRecord(Record, String):123, BinaryOutputArchive (org.apache.jute), BinaryOutputArchive.java writePacket(QuorumPacket, boolean):139, Learner (org.apache.zookeeper.server.quorum), Learner.java request(Request):191, Learner (org.apache.zookeeper.server.quorum), Learner.java run():96, FollowerRequestProcessor (org.apache.zookeeper.server.quorum), FollowerRequestProcessor.javaFollowerRequestProcessor是一个线程在zk启动的时候就开始运行,主要逻辑在run方法里面,run方法的主要逻辑是
先把请求提交给CommitProcessor(后面leader发送给follower的commit请求对应到这里),然后将请求转发给leader,转发给leader的过程就是构造一个QuorumPacket,通过之前选举通信的端口发送给leader。
leader接收follower请求leader获取leader地位以后,启动learnhandler,然后一直在LearnerHandler#run循环,接收来自learner的packet,处理流程是:
processRequest(Request):1003, org.apache.zookeeper.server.PrepRequestProcessor.java submitLearnerRequest(Request):150, org.apache.zookeeper.server.quorum.LeaderZooKeeperServer.java run():625, org.apache.zookeeper.server.quorum.LearnerHandler.javahandler判断是REQUEST请求的话交给leader的processor链处理,将请求放入org.apache.zookeeper.server.PrepRequestProcessor#submittedRequests,即leader的第一个processor。这个processor也是一个线程,从submittedRequests中不断拿出请求处理
processor主要做了:
交给CommitProcessor等待提交
交给leader的下一个processor处理:ProposalRequestProcessor
leader 发送proposal给followerProposalRequestProcessor主要作用就是讲请求交给下一个processor并且发起投票,将proposal发送给所有的follower。
// org.apache.zookeeper.server.quorum.Leader#sendPacket void sendPacket(QuorumPacket qp) { synchronized (forwardingFollowers) { // 所有的follower,observer没有投票权 for (LearnerHandler f : forwardingFollowers) { f.queuePacket(qp); } } } follower 收到proposalfollower处理proposal请求的调用堆栈
processRequest(Request):214, org.apache.zookeeper.server.SyncRequestProcessor.java logRequest(TxnHeader, Record):89, org.apache.zookeeper.server.quorumFollowerZooKeeperServer.java processPacket(QuorumPacket):147, org.apache.zookeeper.server.quorum.Follower.java followLeader():102, org.apache.zookeeper.server.quorum.Follower.java run():1199, org.apache.zookeeper.server.quorum.QuorumPeer.java将请求放入org.apache.zookeeper.server.SyncRequestProcessor#queuedRequests
follower 发送ack线程SyncRequestProcessor#run从org.apache.zookeeper.server.SyncRequestProcessor#toFlush中取出请求flush,处理过程
follower开始commit,记录txLog和snapShot
发送commit成功请求给leader,也就是follower给leader的ACK
leader收到ackleader 收到ack后判断是否收到大多数的follower的ack,如果是说明可以commit,commit后同步给follower
还是Follower#followLeader里面的while循环收到leader的commit请求后,调用下面的方法处理
org.apache.zookeeper.server.quorum.FollowerZooKeeperServer#commit
最终加入CommitProcessor.committedRequests队列,CommitProcessor主线程发现队列不空表明需要把这个request转发到下一个processor
follower发送请求给客户端follower的最后一个processor是FinalRequestProcessor,最后会创建对应的节点并且构造response返回给client
总结本篇文章主要介绍了client发起一次写请求,client、follower和leader各自的处理过程。当然了,为了简单,其中设定了一些具体的场景,比如请求是发送到follower的而不是leader。