处理写请求总体过程
客户端发起写请求
follower和leader交互过程
follower发送请求给客户端
处理写请求总体过程zk为了保证分布式数据一致性,使用ZAB协议,在客户端发起一次写请求的时候时候,假设该请求请求到的是follower,follower不会直接处理这个请求,而是转发给leader,由leader发起投票决定该请求最终能否执行成功,所以整个过程client、被请求的follower、leader、其他follower都参与其中。以创建一个节点为例,总体流程如下
从图中可以看出,创建流程为
follower接受请求,解析请求
follower通过FollowerRequestProcessor将请求转发给leader
leader接收请求
leader发送proposal给follower
follower收到请求记录txlog、snapshot
follower发送ack给leader
leader收到ack后进行commit,并且通知所有的learner,发送commit packet给所有的learner
这里说的follower、leader都是server,在zk里面server总共有这么几种
由于server角色不同,对于请求所做的处理不同,每种server包含的processor也不同,下面细说下具体有哪些processor。
follower的processor链这里的follower是FollowerZooKeeperServer,通过setupRequestProcessors来设置自己的processor链
FollowerRequestProcessor -> CommitProcessor ->FinalRequestProcessor每个processor对应的功能为:
FollowerRequestProcessor:作用:将请求先转发给下一个processor,然后根据不同的OpCode做不同的操作
如果是:sync,先加入org.apache.zookeeper.server.quorum.FollowerZooKeeperServer#pendingSyncs,然后发送给leader
如果是:create等,直接转发
如果是:createSession或者closeSession,如果不是localsession则转发给leader
CommitProcessor :有一个WorkerService,将请求封装为CommitWorkRequest执行
作用:
转发请求,读请求直接转发给下一个processor
写请求先放在pendingRequests对应的sessionId下的list中,收到leader返回的commitRequest再处理
处理读请求(不会改变服务器状态的请求)
处理committed的写请求(经过leader 处理完成的请求)
维护一个线程池服务WorkerService,每个请求都在单独的线程中处理
每个session的请求必须按顺序执行
写请求必须按照zxid顺序执行
确认一个session中写请求之间没有竞争
FinalRequestProcessor:总是processor chain上最后一个processor
作用:
实际处理事务请求的processor
处理query请求
返回response给客户端
SyncRequestProcessor:作用:
接收leader的proposal进行处理
从org.apache.zookeeper.server.SyncRequestProcessor#queuedRequests中取出请求记录txlog和snapshot
然后加入toFlush,从toFlush中取出请求交给org.apache.zookeeper.server.quorum.SendAckRequestProcessor#flush处理
leader的processor链这里的leader就是LeaderZooKeeperServer
通过setupRequestProcessors来设置自己的processor链
PrepRequestProcessor -> ProposalRequestProcessor ->CommitProcessor -> Leader.ToBeAppliedRequestProcessor ->FinalRequestProcessor 客户端发起写请求在客户端启动的时候会创建Zookeeper实例,client会连接到server,后面client在创建节点的时候就可以直接和server通信,client发起创建创建节点请求的过程是:
org.apache.zookeeper.ZooKeeper#create(java.lang.String, byte[], java.util.List<org.apache.zookeeper.data.ACL>, org.apache.zookeeper.CreateMode) org.apache.zookeeper.ClientCnxn#submitRequest org.apache.zookeeper.ClientCnxn#queuePacket在ZooKeeper#create方法中构造请求的request
在ClientCnxn#queuePacket方法中将request封装到packet中,将packet放入发送队列outgoingQueue中等待发送
SendThread不断从发送队列outgoingQueue中取出packet发送
通过 packet.wait等待server返回
follower和leader交互过程client发出请求后,follower会接收并处理该请求。选举结束后follower确定了自己的角色为follower,一个端口和client通信,一个端口和leader通信。监听到来自client的连接口建立新的session,监听对应的socket上的读写事件,如果client有请求发到follower,follower会用下面的方法处理
org.apache.zookeeper.server.NIOServerCnxn#readPayload org.apache.zookeeper.server.NIOServerCnxn#readRequestreadPayload这个方法里面会判断是连接请求还是非连接请求,连接请求在之前session建立的文章中介绍过,这里从处理非连接请求开始。
follower接收client请求