zookeeper源码 — 五、处理写请求过程

处理写请求总体过程

客户端发起写请求

follower和leader交互过程

follower发送请求给客户端

处理写请求总体过程

zk为了保证分布式数据一致性,使用ZAB协议,在客户端发起一次写请求的时候时候,假设该请求请求到的是follower,follower不会直接处理这个请求,而是转发给leader,由leader发起投票决定该请求最终能否执行成功,所以整个过程client、被请求的follower、leader、其他follower都参与其中。以创建一个节点为例,总体流程如下

zookeeper源码 — 五、处理写请求过程

从图中可以看出,创建流程为

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总共有这么几种

zookeeper源码 — 五、处理写请求过程

由于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#readRequest

readPayload这个方法里面会判断是连接请求还是非连接请求,连接请求在之前session建立的文章中介绍过,这里从处理非连接请求开始。

follower接收client请求

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zydffd.html