www

导航

zookeeper选举(四)-Follower.followLeader()

    void followLeader() {
        try {
            QuorumServer leaderServer = findLeader();
            try {
                // 与Leader建立连接,Leader端LearnHandle处理
                connectToLeader(leaderServer.addr, leaderServer.hostname);
                // Leader同步最新起始zxid
                long newEpochZxid = registerWithLeader(Leader.FOLLOWERINFO);
                long newEpoch = ZxidUtils.getEpochFromZxid(newEpochZxid);
                // 这种情况一般不会发生(极端情况会出现,由此区分currentEpoch和acceptedEpoch)
                if (newEpoch < self.getAcceptedEpoch()) {
                    LOG.error("Proposed leader epoch " + ZxidUtils.zxidToString(newEpochZxid)
                            + " is less than our accepted epoch " + ZxidUtils.zxidToString(self.getAcceptedEpoch()));
                    throw new IOException("Error: Epoch of leader is lower");
                }
                syncWithLeader(newEpochZxid);
                QuorumPacket qp = new QuorumPacket();
                // 循环,接收其他节点发来的事务请求
                while (this.isRunning()) {
                    readPacket(qp);
                    processPacket(qp);
                }
            } catch (Exception e) {
                LOG.warn("Exception when following the leader", e);
                try {
                    sock.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }

                pendingRevalidations.clear();
            }
        } finally {
            zk.unregisterJMX(this);
        }
    }
    /**
     * Once connected to the leader, perform the handshake protocol to
     * establish a following / observing connection.
     */
    long registerWithLeader(int pktType) throws IOException {
        // Send follower info, including last zxid and sid
        long lastLoggedZxid = self.getLastLoggedZxid();
        QuorumPacket qp = new QuorumPacket();
        // Leader.FOLLOWER_INFO
        qp.setType(pktType);
        qp.setZxid(ZxidUtils.makeZxid(self.getAcceptedEpoch(), 0));
        ByteArrayOutputStream bsid = new ByteArrayOutputStream();
        BinaryOutputArchive boa = BinaryOutputArchive.getArchive(bsid);
        boa.writeRecord(new LearnerInfo(self.getId(), 0x10000), "LearnerInfo");
        qp.setData(bsid.toByteArray());
        writePacket(qp, true);

        // Leader.LEADER_INFO
        readPacket(qp);
        final long newEpoch = ZxidUtils.getEpochFromZxid(qp.getZxid());
        if (qp.getType() == Leader.LEADERINFO) {
            // we are connected to a 1.0 server so accept the new epoch and read the next packet
            leaderProtocolVersion = ByteBuffer.wrap(qp.getData()).getInt();
            byte[] epochBytes = new byte[4];
            final ByteBuffer wrappedEpochBytes = ByteBuffer.wrap(epochBytes);
            if (newEpoch > self.getAcceptedEpoch()) {
                wrappedEpochBytes.putInt((int) self.getCurrentEpoch());
                self.setAcceptedEpoch(newEpoch);
            } else if (newEpoch == self.getAcceptedEpoch()) {
                wrappedEpochBytes.putInt(-1);
            } else {
                throw new IOException("Leaders epoch, " + newEpoch + " is less than accepted epoch, " + self.getAcceptedEpoch());
            }
            QuorumPacket ackNewEpoch = new QuorumPacket(Leader.ACKEPOCH, lastLoggedZxid, epochBytes, null);
            writePacket(ackNewEpoch, true);
            return ZxidUtils.makeZxid(newEpoch, 0);
        } else {
            if (newEpoch > self.getAcceptedEpoch()) {
                self.setAcceptedEpoch(newEpoch);
            }
            if (qp.getType() != Leader.NEWLEADER) {
                LOG.error("First packet should have been NEWLEADER");
                throw new IOException("First packet should have been NEWLEADER");
            }
            return qp.getZxid();
        }
    }

posted on 2020-10-01 13:23  www_practice  阅读(244)  评论(0编辑  收藏  举报