Search in sources :

Example 1 with QuorumServer

use of org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer in project zookeeper by apache.

the class LeaderElection method lookForLeader.

/**
     * Invoked in QuorumPeer to find or elect a new leader.
     * 
     * @throws InterruptedException
     */
public Vote lookForLeader() throws InterruptedException {
    try {
        self.jmxLeaderElectionBean = new LeaderElectionBean();
        MBeanRegistry.getInstance().register(self.jmxLeaderElectionBean, self.jmxLocalPeerBean);
    } catch (Exception e) {
        LOG.warn("Failed to register with JMX", e);
        self.jmxLeaderElectionBean = null;
    }
    try {
        self.setCurrentVote(new Vote(self.getId(), self.getLastLoggedZxid()));
        // We are going to look for a leader by casting a vote for ourself
        byte[] requestBytes = new byte[4];
        ByteBuffer requestBuffer = ByteBuffer.wrap(requestBytes);
        byte[] responseBytes = new byte[28];
        ByteBuffer responseBuffer = ByteBuffer.wrap(responseBytes);
        /* The current vote for the leader. Initially me! */
        DatagramSocket s = null;
        try {
            s = new DatagramSocket();
            s.setSoTimeout(200);
        } catch (SocketException e1) {
            LOG.error("Socket exception when creating socket for leader election", e1);
            System.exit(4);
        }
        DatagramPacket requestPacket = new DatagramPacket(requestBytes, requestBytes.length);
        DatagramPacket responsePacket = new DatagramPacket(responseBytes, responseBytes.length);
        int xid = epochGen.nextInt();
        while (self.isRunning()) {
            HashMap<InetSocketAddress, Vote> votes = new HashMap<InetSocketAddress, Vote>(self.getVotingView().size());
            requestBuffer.clear();
            requestBuffer.putInt(xid);
            requestPacket.setLength(4);
            HashSet<Long> heardFrom = new HashSet<Long>();
            for (QuorumServer server : self.getVotingView().values()) {
                LOG.info("Server address: " + server.addr);
                try {
                    requestPacket.setSocketAddress(server.addr);
                } catch (IllegalArgumentException e) {
                    // in order to capture this critical detail.
                    throw new IllegalArgumentException("Unable to set socket address on packet, msg:" + e.getMessage() + " with addr:" + server.addr, e);
                }
                try {
                    s.send(requestPacket);
                    responsePacket.setLength(responseBytes.length);
                    s.receive(responsePacket);
                    if (responsePacket.getLength() != responseBytes.length) {
                        LOG.error("Got a short response: " + responsePacket.getLength());
                        continue;
                    }
                    responseBuffer.clear();
                    int recvedXid = responseBuffer.getInt();
                    if (recvedXid != xid) {
                        LOG.error("Got bad xid: expected " + xid + " got " + recvedXid);
                        continue;
                    }
                    long peerId = responseBuffer.getLong();
                    heardFrom.add(peerId);
                    //if(server.id != peerId){
                    Vote vote = new Vote(responseBuffer.getLong(), responseBuffer.getLong());
                    InetSocketAddress addr = (InetSocketAddress) responsePacket.getSocketAddress();
                    votes.put(addr, vote);
                //}
                } catch (IOException e) {
                    LOG.warn("Ignoring exception while looking for leader", e);
                // Errors are okay, since hosts may be
                // down
                }
            }
            ElectionResult result = countVotes(votes, heardFrom);
            // for a dead peer                 
            if (result.numValidVotes == 0) {
                self.setCurrentVote(new Vote(self.getId(), self.getLastLoggedZxid()));
            } else {
                if (result.winner.getId() >= 0) {
                    self.setCurrentVote(result.vote);
                    // To do: this doesn't use a quorum verifier
                    if (result.winningCount > (self.getVotingView().size() / 2)) {
                        self.setCurrentVote(result.winner);
                        s.close();
                        Vote current = self.getCurrentVote();
                        LOG.info("Found leader: my type is: " + self.getLearnerType());
                        /*
                             * We want to make sure we implement the state machine
                             * correctly. If we are a PARTICIPANT, once a leader
                             * is elected we can move either to LEADING or 
                             * FOLLOWING. However if we are an OBSERVER, it is an
                             * error to be elected as a Leader.
                             */
                        if (self.getLearnerType() == LearnerType.OBSERVER) {
                            if (current.getId() == self.getId()) {
                                // This should never happen!
                                LOG.error("OBSERVER elected as leader!");
                                Thread.sleep(100);
                            } else {
                                self.setPeerState(ServerState.OBSERVING);
                                Thread.sleep(100);
                                return current;
                            }
                        } else {
                            self.setPeerState((current.getId() == self.getId()) ? ServerState.LEADING : ServerState.FOLLOWING);
                            if (self.getPeerState() == ServerState.FOLLOWING) {
                                Thread.sleep(100);
                            }
                            return current;
                        }
                    }
                }
            }
            Thread.sleep(1000);
        }
        return null;
    } finally {
        try {
            if (self.jmxLeaderElectionBean != null) {
                MBeanRegistry.getInstance().unregister(self.jmxLeaderElectionBean);
            }
        } catch (Exception e) {
            LOG.warn("Failed to unregister with JMX", e);
        }
        self.jmxLeaderElectionBean = null;
    }
}
Also used : SocketException(java.net.SocketException) Vote(org.apache.zookeeper.server.quorum.Vote) HashMap(java.util.HashMap) InetSocketAddress(java.net.InetSocketAddress) QuorumServer(org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer) IOException(java.io.IOException) SocketException(java.net.SocketException) DatagramSocket(java.net.DatagramSocket) DatagramPacket(java.net.DatagramPacket) HashSet(java.util.HashSet)

Example 2 with QuorumServer

use of org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer in project zookeeper by apache.

the class CnxManagerTest method testCnxManagerTimeout.

@Test
public void testCnxManagerTimeout() throws Exception {
    Random rand = new Random();
    byte b = (byte) rand.nextInt();
    int deadPort = PortAssignment.unique();
    String deadAddress = "10.1.1." + b;
    LOG.info("This is the dead address I'm trying: " + deadAddress);
    peers.put(Long.valueOf(2), new QuorumServer(2, new InetSocketAddress(deadAddress, deadPort), new InetSocketAddress(deadAddress, PortAssignment.unique()), new InetSocketAddress(deadAddress, PortAssignment.unique())));
    peerTmpdir[2] = ClientBase.createTmpDir();
    QuorumPeer peer = new QuorumPeer(peers, peerTmpdir[1], peerTmpdir[1], peerClientPort[1], 3, 1, 1000, 2, 2);
    QuorumCnxManager cnxManager = peer.createCnxnManager();
    QuorumCnxManager.Listener listener = cnxManager.listener;
    if (listener != null) {
        listener.start();
    } else {
        LOG.error("Null listener when initializing cnx manager");
    }
    long begin = Time.currentElapsedTime();
    cnxManager.toSend(2L, createMsg(ServerState.LOOKING.ordinal(), 1, -1, 1));
    long end = Time.currentElapsedTime();
    if ((end - begin) > 6000)
        Assert.fail("Waited more than necessary");
    cnxManager.halt();
    Assert.assertFalse(cnxManager.listener.isAlive());
}
Also used : Random(java.util.Random) QuorumServer(org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer) InetSocketAddress(java.net.InetSocketAddress) QuorumPeer(org.apache.zookeeper.server.quorum.QuorumPeer) QuorumCnxManager(org.apache.zookeeper.server.quorum.QuorumCnxManager) Test(org.junit.Test)

Example 3 with QuorumServer

use of org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer in project rest.li by linkedin.

the class ZKQuorum method createNewPeerData.

private void createNewPeerData(int id) {
    int clientPort = ZKTestUtil.getRandomPort();
    int quorumPort = ZKTestUtil.getRandomPort() + 1000;
    int electionPort = ZKTestUtil.getRandomPort() + 1001;
    ZKPeer zkpeer = new ZKPeer(id, ZKTestUtil.createTempDir("zkdata" + id), ZKTestUtil.createTempDir("zklog" + id), HOST, clientPort, quorumPort, electionPort);
    _peers.put(id, zkpeer);
    _peersView.put(Long.valueOf(id), new QuorumServer(id, HOST, quorumPort, electionPort, LearnerType.PARTICIPANT));
    _log.info("Created peer #" + id + " with ports:" + clientPort + "/" + quorumPort + "/" + electionPort + "  peer server addr:" + _peersView.get(Long.valueOf(id)).addr + "  peer server electionAddr:" + _peersView.get(Long.valueOf(id)).electionAddr);
}
Also used : QuorumServer(org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer)

Example 4 with QuorumServer

use of org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer in project zookeeper by apache.

the class Observer method findLearnerMaster.

private QuorumServer findLearnerMaster() {
    QuorumPeer.QuorumServer prescribedLearnerMaster = nextLearnerMaster.getAndSet(null);
    if (prescribedLearnerMaster != null && self.validateLearnerMaster(Long.toString(prescribedLearnerMaster.id)) == null) {
        LOG.warn("requested next learner master {} is no longer valid", prescribedLearnerMaster);
        prescribedLearnerMaster = null;
    }
    final QuorumPeer.QuorumServer master = (prescribedLearnerMaster == null) ? self.findLearnerMaster(findLeader()) : prescribedLearnerMaster;
    currentLearnerMaster = master;
    if (master == null) {
        LOG.warn("No learner master found");
    } else {
        LOG.info("Observing new leader sid={} addr={}", master.id, master.addr);
    }
    return master;
}
Also used : QuorumServer(org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer)

Example 5 with QuorumServer

use of org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer in project zookeeper by apache.

the class Follower method followLeader.

/**
 * the main method called by the follower to follow the leader
 *
 * @throws InterruptedException
 */
void followLeader() throws InterruptedException {
    self.end_fle = Time.currentElapsedTime();
    long electionTimeTaken = self.end_fle - self.start_fle;
    self.setElectionTimeTaken(electionTimeTaken);
    ServerMetrics.getMetrics().ELECTION_TIME.add(electionTimeTaken);
    LOG.info("FOLLOWING - LEADER ELECTION TOOK - {} {}", electionTimeTaken, QuorumPeer.FLE_TIME_UNIT);
    self.start_fle = 0;
    self.end_fle = 0;
    fzk.registerJMX(new FollowerBean(this, zk), self.jmxLocalPeerBean);
    long connectionTime = 0;
    boolean completedSync = false;
    try {
        self.setZabState(QuorumPeer.ZabState.DISCOVERY);
        QuorumServer leaderServer = findLeader();
        try {
            connectToLeader(leaderServer.addr, leaderServer.hostname);
            connectionTime = System.currentTimeMillis();
            long newEpochZxid = registerWithLeader(Leader.FOLLOWERINFO);
            if (self.isReconfigStateChange()) {
                throw new Exception("learned about role change");
            }
            // check to see if the leader zxid is lower than ours
            // this should never happen but is just a safety check
            long newEpoch = ZxidUtils.getEpochFromZxid(newEpochZxid);
            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");
            }
            long startTime = Time.currentElapsedTime();
            self.setLeaderAddressAndId(leaderServer.addr, leaderServer.getId());
            self.setZabState(QuorumPeer.ZabState.SYNCHRONIZATION);
            syncWithLeader(newEpochZxid);
            self.setZabState(QuorumPeer.ZabState.BROADCAST);
            completedSync = true;
            long syncTime = Time.currentElapsedTime() - startTime;
            ServerMetrics.getMetrics().FOLLOWER_SYNC_TIME.add(syncTime);
            if (self.getObserverMasterPort() > 0) {
                LOG.info("Starting ObserverMaster");
                om = new ObserverMaster(self, fzk, self.getObserverMasterPort());
                om.start();
            } else {
                om = null;
            }
            // create a reusable packet to reduce gc impact
            QuorumPacket qp = new QuorumPacket();
            while (this.isRunning()) {
                readPacket(qp);
                processPacket(qp);
            }
        } catch (Exception e) {
            LOG.warn("Exception when following the leader", e);
            closeSocket();
            // clear pending revalidations
            pendingRevalidations.clear();
        }
    } finally {
        if (om != null) {
            om.stop();
        }
        zk.unregisterJMX(this);
        if (connectionTime != 0) {
            long connectionDuration = System.currentTimeMillis() - connectionTime;
            LOG.info("Disconnected from leader (with address: {}). Was connected for {}ms. Sync state: {}", leaderAddr, connectionDuration, completedSync);
            messageTracker.dumpToLog(leaderAddr.toString());
        }
    }
}
Also used : QuorumServer(org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer) IOException(java.io.IOException) IOException(java.io.IOException)

Aggregations

QuorumServer (org.apache.zookeeper.server.quorum.QuorumPeer.QuorumServer)59 InetSocketAddress (java.net.InetSocketAddress)30 Test (org.junit.jupiter.api.Test)22 QuorumPeer (org.apache.zookeeper.server.quorum.QuorumPeer)17 HashMap (java.util.HashMap)13 IOException (java.io.IOException)9 File (java.io.File)8 ArrayList (java.util.ArrayList)6 BeforeEach (org.junit.jupiter.api.BeforeEach)6 ServerSocket (java.net.ServerSocket)3 Socket (java.net.Socket)3 ByteBuffer (java.nio.ByteBuffer)3 Properties (java.util.Properties)3 KeeperException (org.apache.zookeeper.KeeperException)3 ZooKeeper (org.apache.zookeeper.ZooKeeper)3 Vote (org.apache.zookeeper.server.quorum.Vote)3 QuorumVerifier (org.apache.zookeeper.server.quorum.flexible.QuorumVerifier)3 Test (org.junit.Test)3 EOFException (java.io.EOFException)2 DatagramPacket (java.net.DatagramPacket)2