zookeeper选主(四)-Leader.lead()
/** * Leader#lead() * <p> * 当前节点是Leader */ void lead() throws IOException, InterruptedException { try { zk.loadData(); // leaderStateSummary-如果有更新的节点突然启动,会导致LearnerHandler中waitForEpochAck抛异常 leaderStateSummary = new StateSummary(self.getCurrentEpoch(), zk.getLastProcessedZxid()); cnxAcceptor = new LearnerCnxAcceptor(); // ip:port1:port2 port1端口为数据通信端口,port2为选举通信端口 cnxAcceptor.start(); // 会在这里阻塞,直到有过半的节点参与,才会唤醒(可能因为超时导致Leader宣告统治失败) long epoch = getEpochToPropose(self.getId(), self.getAcceptedEpoch()); zk.setZxid(ZxidUtils.makeZxid(epoch, 0)); synchronized (this) { lastProposed = zk.getZxid(); } newLeaderProposal.packet = new QuorumPacket(NEWLEADER, zk.getZxid(), null, null); // 在这里阻塞,可能因为超时导致新Leader宣告统治失败 waitForEpochAck(self.getId(), leaderStateSummary); self.setCurrentEpoch(epoch); try { // 统一zxid,也可能宣告统治失败 waitForNewLeaderAck(self.getId(), zk.getZxid()); } catch (InterruptedException e) { shutdown("Waiting for a quorum of followers, only synced with sids: [ " + getSidSetString(newLeaderProposal.ackSet) + " ]"); HashSet<Long> followerSet = new HashSet<>(); for (LearnerHandler f : learners) { followerSet.add(f.getSid()); } // 重点,时间设置过短 if (self.getQuorumVerifier().containsQuorum(followerSet)) { LOG.warn("Enough followers present. " + "Perhaps the initTicks need to be increased."); } Thread.sleep(self.tickTime); self.tick.incrementAndGet(); // 正常退出,重新选主 return; } // 选主结束 // 启动zk服务,对外提供服务 startZkServer(); String initialZxid = System.getProperty("zookeeper.testingonly.initialZxid"); if (initialZxid != null) { long zxid = Long.parseLong(initialZxid); zk.setZxid((zk.getZxid() & 0xffffffff00000000L) | zxid); } if (!System.getProperty("zookeeper.leaderServes", "yes").equals("no")) { self.cnxnFactory.setZooKeeperServer(zk); } boolean tickSkip = true; // 心跳检测 while (true) { Thread.sleep(self.tickTime / 2); if (!tickSkip) { self.tick.incrementAndGet(); } HashSet<Long> syncedSet = new HashSet<>(); syncedSet.add(self.getId()); for (LearnerHandler learnerHandler : getLearners()) { if (learnerHandler.synced() && learnerHandler.getLearnerType() == LearnerType.PARTICIPANT) { syncedSet.add(learnerHandler.getSid()); } learnerHandler.ping(); } if (!this.isRunning()) { shutdown("Unexpected internal error"); return; } if (!tickSkip && !self.getQuorumVerifier().containsQuorum(syncedSet)) { shutdown("Not sufficient followers synced, only synced with sids: [ " + getSidSetString(syncedSet) + " ]"); return; } tickSkip = !tickSkip; } } finally { zk.unregisterJMX(this); } }
/** * LearnerCnxAcceptor.start() */ @Override public void run() { try { while (!stop) { try { Socket connSocket = ss.accept(); connSocket.setSoTimeout(self.tickTime * self.initLimit); connSocket.setTcpNoDelay(nodelay); BufferedInputStream is = new BufferedInputStream( connSocket.getInputStream()); LearnerHandler learnerHandler = new LearnerHandler(connSocket, is, Leader.this); learnerHandler.start(); } catch (SocketException e) { if (stop) { stop = true; } else { throw e; } } catch (SaslException e) { LOG.error("Exception while connecting to quorum learner", e); } } } catch (Exception e) { LOG.warn("Exception while accepting follower", e); } } void halt() { stop = true; } }
/** * Leader#getEpochToPropose()和LearnerHandler#getEpochToPropose() * <p> * 和LearnerHandler(与其他节点的一对一连接) */ long getEpochToPropose(long sid, long lastAcceptedEpoch) throws InterruptedException, IOException { synchronized (connectingFollowers) { // 重点,如果已经新的统治轮次计算完成,直接返回 if (!waitingForNewEpoch) { return epoch; } if (lastAcceptedEpoch >= epoch) { epoch = lastAcceptedEpoch + 1; } if (isParticipant(sid)) { connectingFollowers.add(sid); } QuorumVerifier verifier = self.getQuorumVerifier(); // 过半原则,计算出新的统治轮次 if (connectingFollowers.contains(self.getId()) && verifier.containsQuorum(connectingFollowers)) { waitingForNewEpoch = false; self.setAcceptedEpoch(epoch); connectingFollowers.notifyAll(); } else { long start = Time.currentElapsedTime(); long cur = start; long end = start + self.getInitLimit() * self.getTickTime(); // 阻塞,超时就退出 while (waitingForNewEpoch && cur < end) { connectingFollowers.wait(end - cur); cur = Time.currentElapsedTime(); } if (waitingForNewEpoch) { throw new InterruptedException("Timeout while waiting for epoch from quorum"); } } return epoch; } }
void waitForEpochAck(long id, StateSummary ss) throws IOException, InterruptedException { synchronized (electingFollowers) { if (electionFinished) { return; } if (ss.getCurrentEpoch() != -1) { if (ss.isMoreRecentThan(leaderStateSummary)) { throw new IOException("Follower is ahead of the leader, leader summary: " + leaderStateSummary.getCurrentEpoch() + " (current epoch), " + leaderStateSummary.getLastZxid() + " (last zxid)"); } if (isParticipant(id)) { electingFollowers.add(id); } } QuorumVerifier verifier = self.getQuorumVerifier(); if (electingFollowers.contains(self.getId()) && verifier.containsQuorum(electingFollowers)) { electionFinished = true; electingFollowers.notifyAll(); } else { long start = Time.currentElapsedTime(); long cur = start; long end = start + self.getInitLimit() * self.getTickTime(); while (!electionFinished && cur < end) { electingFollowers.wait(end - cur); cur = Time.currentElapsedTime(); } if (!electionFinished) { throw new InterruptedException("Timeout while waiting for epoch to be acked by quorum"); } } } }
posted on 2020-10-01 12:44 www_practice 阅读(326) 评论(0) 编辑 收藏 举报