leader和follower启动期交互过程包括如下步骤。
1.创建Leader服务器和Follower服务器
完成leader选举后,各服务器会根据自己角色创建相应的服务器实例,并开始进入各自角色的主流程。
代码位置:QuorumPeer.java
leader
case LEADING: LOG.info("LEADING"); try { setLeader(makeLeader(logFactory)); leader.lead(); setLeader(null); }
follower
case FOLLOWING: try { LOG.info("FOLLOWING"); setFollower(makeFollower(logFactory)); follower.followLeader(); }
2.leader服务器启动follower接收器LearnerCnxAcceptor。
LearnerCnxAcceptor接收器用于负责接收所有非leader服务器的连接请求。
Leader的lead过程
void lead() throws IOException, InterruptedException {
...
self.tick = 0;
//从本地文件恢复数据
zk.loadData();
//leader的状态信息
leaderStateSummary = new StateSummary(self.getCurrentEpoch(), zk.getLastProcessedZxid());
// Start thread that waits for connection requests from
// new followers.
//启动lead端口的监听线程,专门用来监听新的follower
cnxAcceptor = new LearnerCnxAcceptor();
cnxAcceptor.start();
readyToStart = true;
//等待足够多的follower进来,代表自己确实是leader,此处lead线程可能会等待
long epoch = getEpochToPropose(self.getId(), self.getAcceptedEpoch());
...
3.learner服务器开始和leader建立连接
所有的learner服务器在启动完毕后,会从leader选举结果中找到leader服务器,然后与其建立连接。
4.leader服务器创建LearnerHandler
leader接收到learner的连接创建请求后,会创建一个LearnerHandler。每一个LearnerHandler实例对应一个leader与learner服务器之间的连接,其负责leader与learner间几乎所有的消息通信和数据同步。
LearnerCnxAcceptor的线程
public void run() {
try {
wh