Search in sources :

Example 46 with RaftPeerId

use of org.apache.ratis.protocol.RaftPeerId in project incubator-ratis by apache.

the class LeaderElectionTests method testEnforceLeader.

@Test
public void testEnforceLeader() throws Exception {
    LOG.info("Running testEnforceLeader");
    final int numServer = 5;
    try (final MiniRaftCluster cluster = newCluster(numServer)) {
        cluster.start();
        final RaftPeerId firstLeader = waitForLeader(cluster).getId();
        LOG.info("firstLeader = {}", firstLeader);
        final int first = MiniRaftCluster.getIdIndex(firstLeader.toString());
        final int random = ThreadLocalRandom.current().nextInt(numServer - 1);
        final String newLeader = "s" + (random < first ? random : random + 1);
        LOG.info("enforce leader to {}", newLeader);
        enforceLeader(cluster, newLeader, LOG);
    }
}
Also used : RaftPeerId(org.apache.ratis.protocol.RaftPeerId) Test(org.junit.Test) BaseTest(org.apache.ratis.BaseTest)

Example 47 with RaftPeerId

use of org.apache.ratis.protocol.RaftPeerId in project incubator-ratis by apache.

the class InstallSnapshotNotificationTests method testInstallSnapshotDuringBootstrap.

private void testInstallSnapshotDuringBootstrap(CLUSTER cluster) throws Exception {
    leaderSnapshotInfoRef.set(null);
    numSnapshotRequests.set(0);
    int i = 0;
    try {
        RaftTestUtil.waitForLeader(cluster);
        final RaftPeerId leaderId = cluster.getLeader().getId();
        try (final RaftClient client = cluster.createClient(leaderId)) {
            for (; i < SNAPSHOT_TRIGGER_THRESHOLD * 2 - 1; i++) {
                RaftClientReply reply = client.io().send(new RaftTestUtil.SimpleMessage("m" + i));
                Assert.assertTrue(reply.isSuccess());
            }
        }
        // wait for the snapshot to be done
        final RaftServer.Division leader = cluster.getLeader();
        final long nextIndex = leader.getRaftLog().getNextIndex();
        LOG.info("nextIndex = {}", nextIndex);
        final List<File> snapshotFiles = RaftSnapshotBaseTest.getSnapshotFiles(cluster, nextIndex - SNAPSHOT_TRIGGER_THRESHOLD, nextIndex);
        JavaUtils.attemptRepeatedly(() -> {
            Assert.assertTrue(snapshotFiles.stream().anyMatch(RaftSnapshotBaseTest::exists));
            return null;
        }, 10, ONE_SECOND, "snapshotFile.exist", LOG);
        RaftSnapshotBaseTest.assertLeaderContent(cluster);
        final SnapshotInfo leaderSnapshotInfo = cluster.getLeader().getStateMachine().getLatestSnapshot();
        final boolean set = leaderSnapshotInfoRef.compareAndSet(null, leaderSnapshotInfo);
        Assert.assertTrue(set);
        // add two more peers
        final MiniRaftCluster.PeerChanges change = cluster.addNewPeers(2, true, true);
        // trigger setConfiguration
        cluster.setConfiguration(change.allPeersInNewConf);
        RaftServerTestUtil.waitAndCheckNewConf(cluster, change.allPeersInNewConf, 0, null);
        // leader snapshot.
        for (RaftServer.Division follower : cluster.getFollowers()) {
            Assert.assertEquals(leaderSnapshotInfo.getIndex(), RaftServerTestUtil.getLatestInstalledSnapshotIndex(follower));
        }
        // Make sure each new peer got one snapshot notification.
        Assert.assertEquals(2, numSnapshotRequests.get());
    } finally {
        cluster.shutdown();
    }
}
Also used : RaftServer(org.apache.ratis.server.RaftServer) SnapshotInfo(org.apache.ratis.statemachine.SnapshotInfo) SingleFileSnapshotInfo(org.apache.ratis.statemachine.impl.SingleFileSnapshotInfo) MiniRaftCluster(org.apache.ratis.server.impl.MiniRaftCluster) RaftClientReply(org.apache.ratis.protocol.RaftClientReply) RaftPeerId(org.apache.ratis.protocol.RaftPeerId) File(java.io.File) RaftClient(org.apache.ratis.client.RaftClient)

Example 48 with RaftPeerId

use of org.apache.ratis.protocol.RaftPeerId in project alluxio by Alluxio.

the class RaftJournalSystem method catchUp.

/**
 * Attempts to catch up. If the master loses leadership during this method, it will return early.
 *
 * The caller is responsible for detecting and responding to leadership changes.
 */
private void catchUp(JournalStateMachine stateMachine, RaftJournalAppender client) throws TimeoutException, InterruptedException {
    long startTime = System.currentTimeMillis();
    long waitBeforeRetry = ServerConfiguration.global().getMs(PropertyKey.MASTER_EMBEDDED_JOURNAL_CATCHUP_RETRY_WAIT);
    // Wait for any outstanding snapshot to complete.
    CommonUtils.waitFor("snapshotting to finish", () -> !stateMachine.isSnapshotting(), WaitForOptions.defaults().setTimeoutMs(10 * Constants.MINUTE_MS));
    OptionalLong endCommitIndex = OptionalLong.empty();
    try {
        // affects the completion time estimate in the logs.
        synchronized (this) {
            // synchronized to appease findbugs; shouldn't make any difference
            RaftPeerId serverId = mServer.getId();
            Optional<RaftProtos.CommitInfoProto> commitInfo = getGroupInfo().getCommitInfos().stream().filter(commit -> serverId.equals(RaftPeerId.valueOf(commit.getServer().getId()))).findFirst();
            if (commitInfo.isPresent()) {
                endCommitIndex = OptionalLong.of(commitInfo.get().getCommitIndex());
            } else {
                throw new IOException("Commit info was not present. Couldn't find the current server's " + "latest commit");
            }
        }
    } catch (IOException e) {
        LogUtils.warnWithException(LOG, "Failed to get raft log information before replay." + " Replay statistics will not be available", e);
    }
    RaftJournalProgressLogger progressLogger = new RaftJournalProgressLogger(mStateMachine, endCommitIndex);
    // leader before trying again.
    while (true) {
        if (mPrimarySelector.getState() != PrimarySelector.State.PRIMARY) {
            return;
        }
        long lastAppliedSN = stateMachine.getLastAppliedSequenceNumber();
        long gainPrimacySN = ThreadLocalRandom.current().nextLong(Long.MIN_VALUE, 0);
        LOG.info("Performing catchup. Last applied SN: {}. Catchup ID: {}", lastAppliedSN, gainPrimacySN);
        Exception ex;
        try {
            CompletableFuture<RaftClientReply> future = client.sendAsync(toRaftMessage(JournalEntry.newBuilder().setSequenceNumber(gainPrimacySN).build()), TimeDuration.valueOf(5, TimeUnit.SECONDS));
            RaftClientReply reply = future.get(5, TimeUnit.SECONDS);
            ex = reply.getException();
        } catch (TimeoutException | ExecutionException | IOException e) {
            ex = e;
        }
        if (ex != null) {
            // LeaderNotReadyException typically indicates Ratis is still replaying the journal.
            if (ex instanceof LeaderNotReadyException) {
                progressLogger.logProgress();
            } else {
                LOG.info("Exception submitting term start entry: {}", ex.toString());
            }
            // avoid excessive retries when server is not ready
            Thread.sleep(waitBeforeRetry);
            continue;
        }
        try {
            CommonUtils.waitFor("term start entry " + gainPrimacySN + " to be applied to state machine", () -> stateMachine.getLastPrimaryStartSequenceNumber() == gainPrimacySN, WaitForOptions.defaults().setInterval(Constants.SECOND_MS).setTimeoutMs(5 * Constants.SECOND_MS));
        } catch (TimeoutException e) {
            LOG.info(e.toString());
            continue;
        }
        // are not leader.
        try {
            CommonUtils.waitFor("check primacySN " + gainPrimacySN + " and lastAppliedSN " + lastAppliedSN + " to be applied to leader", () -> stateMachine.getLastAppliedSequenceNumber() == lastAppliedSN && stateMachine.getLastPrimaryStartSequenceNumber() == gainPrimacySN, WaitForOptions.defaults().setInterval(Constants.SECOND_MS).setTimeoutMs((int) mConf.getMaxElectionTimeoutMs()));
        } catch (TimeoutException e) {
            // Restart the catchup process.
            continue;
        }
        LOG.info("Caught up in {}ms. Last sequence number from previous term: {}.", System.currentTimeMillis() - startTime, stateMachine.getLastAppliedSequenceNumber());
        return;
    }
}
Also used : Arrays(java.util.Arrays) GroupInfoReply(org.apache.ratis.protocol.GroupInfoReply) RaftGroup(org.apache.ratis.protocol.RaftGroup) LeaderNotReadyException(org.apache.ratis.protocol.exceptions.LeaderNotReadyException) LoggerFactory(org.slf4j.LoggerFactory) TimeoutException(java.util.concurrent.TimeoutException) PropertyKey(alluxio.conf.PropertyKey) GrpcService(alluxio.grpc.GrpcService) LogUtils(alluxio.util.LogUtils) NetUtils(org.apache.ratis.util.NetUtils) JournalQueryRequest(alluxio.grpc.JournalQueryRequest) MetricKey(alluxio.metrics.MetricKey) Map(java.util.Map) RaftConfigKeys(org.apache.ratis.RaftConfigKeys) CancelledException(alluxio.exception.status.CancelledException) UnsafeByteOperations(org.apache.ratis.thirdparty.com.google.protobuf.UnsafeByteOperations) QuorumServerInfo(alluxio.grpc.QuorumServerInfo) ServerConfiguration(alluxio.conf.ServerConfiguration) RaftPeer(org.apache.ratis.protocol.RaftPeer) RetryPolicy(org.apache.ratis.retry.RetryPolicy) Master(alluxio.master.Master) Collection(java.util.Collection) AbstractJournalSystem(alluxio.master.journal.AbstractJournalSystem) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) Set(java.util.Set) SupportedRpcType(org.apache.ratis.rpc.SupportedRpcType) CompletionException(java.util.concurrent.CompletionException) ThreadSafe(javax.annotation.concurrent.ThreadSafe) UUID(java.util.UUID) InetSocketAddress(java.net.InetSocketAddress) Collectors(java.util.stream.Collectors) List(java.util.List) ClientId(org.apache.ratis.protocol.ClientId) RaftClientReply(org.apache.ratis.protocol.RaftClientReply) RaftProperties(org.apache.ratis.conf.RaftProperties) ServiceType(alluxio.grpc.ServiceType) ExponentialBackoffRetry(org.apache.ratis.retry.ExponentialBackoffRetry) Optional(java.util.Optional) PrimarySelector(alluxio.master.PrimarySelector) RatisDropwizardExports(alluxio.metrics.sink.RatisDropwizardExports) AccessDeniedException(java.nio.file.AccessDeniedException) RaftClientConfigKeys(org.apache.ratis.client.RaftClientConfigKeys) UnavailableException(alluxio.exception.status.UnavailableException) TimeDuration(org.apache.ratis.util.TimeDuration) AsyncJournalWriter(alluxio.master.journal.AsyncJournalWriter) GroupInfoRequest(org.apache.ratis.protocol.GroupInfoRequest) CatchupFuture(alluxio.master.journal.CatchupFuture) SetConfigurationRequest(org.apache.ratis.protocol.SetConfigurationRequest) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) AtomicReference(java.util.concurrent.atomic.AtomicReference) ArrayList(java.util.ArrayList) JournalEntry(alluxio.proto.journal.Journal.JournalEntry) WaitForOptions(alluxio.util.WaitForOptions) RaftGroupId(org.apache.ratis.protocol.RaftGroupId) AddQuorumServerRequest(alluxio.grpc.AddQuorumServerRequest) Message(org.apache.ratis.protocol.Message) OptionalLong(java.util.OptionalLong) Constants(alluxio.Constants) QuorumServerState(alluxio.grpc.QuorumServerState) ThreadLocalRandom(java.util.concurrent.ThreadLocalRandom) MetricsSystem(alluxio.metrics.MetricsSystem) LinkedList(java.util.LinkedList) SizeInBytes(org.apache.ratis.util.SizeInBytes) Nullable(javax.annotation.Nullable) Logger(org.slf4j.Logger) NetAddress(alluxio.grpc.NetAddress) Iterator(java.util.Iterator) RaftPeerId(org.apache.ratis.protocol.RaftPeerId) RaftServerConfigKeys(org.apache.ratis.server.RaftServerConfigKeys) ExceptionMessage(alluxio.exception.ExceptionMessage) RaftProtos(org.apache.ratis.proto.RaftProtos) FileUtils(org.apache.commons.io.FileUtils) GrpcConfigKeys(org.apache.ratis.grpc.GrpcConfigKeys) RaftClientRequest(org.apache.ratis.protocol.RaftClientRequest) IOException(java.io.IOException) TransferLeaderMessage(alluxio.grpc.TransferLeaderMessage) HostAndPort(com.google.common.net.HostAndPort) File(java.io.File) ExecutionException(java.util.concurrent.ExecutionException) TimeUnit(java.util.concurrent.TimeUnit) Parameters(org.apache.ratis.conf.Parameters) AtomicLong(java.util.concurrent.atomic.AtomicLong) LifeCycle(org.apache.ratis.util.LifeCycle) Preconditions(com.google.common.base.Preconditions) VisibleForTesting(com.google.common.annotations.VisibleForTesting) RaftServer(org.apache.ratis.server.RaftServer) RaftClient(org.apache.ratis.client.RaftClient) Comparator(java.util.Comparator) Journal(alluxio.master.journal.Journal) Collections(java.util.Collections) CommonUtils(alluxio.util.CommonUtils) LeaderNotReadyException(org.apache.ratis.protocol.exceptions.LeaderNotReadyException) IOException(java.io.IOException) LeaderNotReadyException(org.apache.ratis.protocol.exceptions.LeaderNotReadyException) TimeoutException(java.util.concurrent.TimeoutException) CancelledException(alluxio.exception.status.CancelledException) CompletionException(java.util.concurrent.CompletionException) AccessDeniedException(java.nio.file.AccessDeniedException) UnavailableException(alluxio.exception.status.UnavailableException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) RaftClientReply(org.apache.ratis.protocol.RaftClientReply) OptionalLong(java.util.OptionalLong) RaftPeerId(org.apache.ratis.protocol.RaftPeerId) ExecutionException(java.util.concurrent.ExecutionException) TimeoutException(java.util.concurrent.TimeoutException)

Example 49 with RaftPeerId

use of org.apache.ratis.protocol.RaftPeerId in project alluxio by Alluxio.

the class RaftJournalSystem method removeQuorumServer.

/**
 * Removes from RAFT quorum, a server with given address.
 * For server to be removed, it should be in unavailable state in quorum.
 *
 * @param serverNetAddress address of the server to remove from the quorum
 * @throws IOException
 */
public synchronized void removeQuorumServer(NetAddress serverNetAddress) throws IOException {
    InetSocketAddress serverAddress = InetSocketAddress.createUnresolved(serverNetAddress.getHost(), serverNetAddress.getRpcPort());
    RaftPeerId peerId = RaftJournalUtils.getPeerId(serverAddress);
    try (RaftClient client = createClient()) {
        Collection<RaftPeer> peers = mServer.getGroups().iterator().next().getPeers();
        RaftClientReply reply = client.admin().setConfiguration(peers.stream().filter(peer -> !peer.getId().equals(peerId)).collect(Collectors.toList()));
        if (reply.getException() != null) {
            throw reply.getException();
        }
    }
}
Also used : RaftClientReply(org.apache.ratis.protocol.RaftClientReply) InetSocketAddress(java.net.InetSocketAddress) RaftPeerId(org.apache.ratis.protocol.RaftPeerId) RaftPeer(org.apache.ratis.protocol.RaftPeer) RaftClient(org.apache.ratis.client.RaftClient)

Example 50 with RaftPeerId

use of org.apache.ratis.protocol.RaftPeerId in project alluxio by Alluxio.

the class RaftJournalSystem method transferLeadership.

/**
 * Transfers the leadership of the quorum to another server.
 *
 * @param newLeaderNetAddress the address of the server
 * @return the guid of transfer leader command
 */
public synchronized String transferLeadership(NetAddress newLeaderNetAddress) {
    final boolean allowed = mTransferLeaderAllowed.getAndSet(false);
    String transferId = UUID.randomUUID().toString();
    if (!allowed) {
        String msg = "transfer is not allowed at the moment because the master is " + (mRaftJournalWriter == null ? "still gaining primacy" : "already transferring the ") + "leadership";
        mErrorMessages.put(transferId, TransferLeaderMessage.newBuilder().setMsg(msg).build());
        return transferId;
    }
    try {
        InetSocketAddress serverAddress = InetSocketAddress.createUnresolved(newLeaderNetAddress.getHost(), newLeaderNetAddress.getRpcPort());
        List<RaftPeer> oldPeers = new ArrayList<>(mRaftGroup.getPeers());
        // The NetUtil function is used by Ratis to convert InetSocketAddress to string
        String strAddr = NetUtils.address2String(serverAddress);
        // if you cannot find the address in the quorum, throw exception.
        if (oldPeers.stream().map(RaftPeer::getAddress).noneMatch(addr -> addr.equals(strAddr))) {
            throw new IOException(String.format("<%s> is not part of the quorum <%s>.", strAddr, oldPeers.stream().map(RaftPeer::getAddress).collect(Collectors.toList())));
        }
        if (strAddr.equals(mRaftGroup.getPeer(mPeerId).getAddress())) {
            throw new IOException(String.format("%s is already the leader", strAddr));
        }
        RaftPeerId newLeaderPeerId = RaftJournalUtils.getPeerId(serverAddress);
        /* update priorities to enable transfer */
        List<RaftPeer> peersWithNewPriorities = new ArrayList<>();
        for (RaftPeer peer : oldPeers) {
            peersWithNewPriorities.add(RaftPeer.newBuilder(peer).setPriority(peer.getId().equals(newLeaderPeerId) ? 2 : 1).build());
        }
        try (RaftClient client = createClient()) {
            String stringPeers = "[" + peersWithNewPriorities.stream().map(RaftPeer::toString).collect(Collectors.joining(", ")) + "]";
            LOG.info("Applying new peer state before transferring leadership: {}", stringPeers);
            RaftClientReply reply = client.admin().setConfiguration(peersWithNewPriorities);
            processReply(reply, "failed to set master priorities before initiating election");
            /* transfer leadership */
            LOG.info("Transferring leadership to master with address <{}> and with RaftPeerId <{}>", serverAddress, newLeaderPeerId);
            // fire and forget: need to immediately return as the master will shut down its RPC servers
            // once the TransferLeadershipRequest is initiated.
            final int SLEEP_TIME_MS = 3_000;
            final int TRANSFER_LEADER_WAIT_MS = 30_000;
            new Thread(() -> {
                try {
                    Thread.sleep(SLEEP_TIME_MS);
                    RaftClientReply reply1 = client.admin().transferLeadership(newLeaderPeerId, TRANSFER_LEADER_WAIT_MS);
                    processReply(reply1, "election failed");
                } catch (Throwable t) {
                    LOG.error("caught an error when executing transfer: {}", t.getMessage());
                    // we only allow transfers again if the transfer is unsuccessful: a success means it
                    // will soon lose primacy
                    mTransferLeaderAllowed.set(true);
                    mErrorMessages.put(transferId, TransferLeaderMessage.newBuilder().setMsg(t.getMessage()).build());
                /* checking the transfer happens in {@link QuorumElectCommand} */
                }
            }).start();
            LOG.info("Transferring leadership initiated");
        }
    } catch (Throwable t) {
        mTransferLeaderAllowed.set(true);
        LOG.warn(t.getMessage());
        mErrorMessages.put(transferId, TransferLeaderMessage.newBuilder().setMsg(t.getMessage()).build());
    }
    return transferId;
}
Also used : InetSocketAddress(java.net.InetSocketAddress) ArrayList(java.util.ArrayList) IOException(java.io.IOException) RaftPeer(org.apache.ratis.protocol.RaftPeer) RaftClientReply(org.apache.ratis.protocol.RaftClientReply) RaftPeerId(org.apache.ratis.protocol.RaftPeerId) RaftClient(org.apache.ratis.client.RaftClient)

Aggregations

RaftPeerId (org.apache.ratis.protocol.RaftPeerId)101 RaftClient (org.apache.ratis.client.RaftClient)58 RaftClientReply (org.apache.ratis.protocol.RaftClientReply)45 IOException (java.io.IOException)36 Test (org.junit.Test)32 RaftPeer (org.apache.ratis.protocol.RaftPeer)31 RaftServer (org.apache.ratis.server.RaftServer)31 BaseTest (org.apache.ratis.BaseTest)21 SimpleMessage (org.apache.ratis.RaftTestUtil.SimpleMessage)20 CompletableFuture (java.util.concurrent.CompletableFuture)18 RaftProperties (org.apache.ratis.conf.RaftProperties)18 File (java.io.File)17 ArrayList (java.util.ArrayList)15 RaftGroupId (org.apache.ratis.protocol.RaftGroupId)15 RaftGroup (org.apache.ratis.protocol.RaftGroup)14 TimeDuration (org.apache.ratis.util.TimeDuration)14 List (java.util.List)13 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)12 Collectors (java.util.stream.Collectors)11 RaftLog (org.apache.ratis.server.raftlog.RaftLog)11