use of org.apache.ratis.protocol.RaftPeer in project incubator-ratis by apache.
the class RetryCacheTests method testRetryOnNewLeader.
/**
* Test retry while the leader changes to another peer
*/
@Test
public void testRetryOnNewLeader() throws Exception {
final MiniRaftCluster cluster = getCluster();
RaftTestUtil.waitForLeader(cluster);
final RaftPeerId leaderId = cluster.getLeaderAndSendFirstMessage().getId();
final RaftClient client = cluster.createClient(leaderId);
RaftClientRpc rpc = client.getClientRpc();
final long callId = 999;
final long seqNum = 111;
RaftClientRequest r = cluster.newRaftClientRequest(client.getId(), leaderId, callId, seqNum, new SimpleMessage("message"));
RaftClientReply reply = rpc.sendRequest(r);
Assert.assertEquals(callId, reply.getCallId());
Assert.assertTrue(reply.isSuccess());
long oldLastApplied = cluster.getLeader().getState().getLastAppliedIndex();
// trigger the reconfiguration, make sure the original leader is kicked out
PeerChanges change = cluster.addNewPeers(2, true);
RaftPeer[] allPeers = cluster.removePeers(2, true, asList(change.newPeers)).allPeersInNewConf;
// trigger setConfiguration
cluster.setConfiguration(allPeers);
RaftTestUtil.waitForLeader(cluster);
final RaftPeerId newLeaderId = cluster.getLeader().getId();
Assert.assertNotEquals(leaderId, newLeaderId);
// same clientId and callId in the request
r = cluster.newRaftClientRequest(client.getId(), newLeaderId, callId, seqNum, new SimpleMessage("message"));
for (int i = 0; i < 10; i++) {
try {
reply = rpc.sendRequest(r);
LOG.info("successfully sent out the retry request_" + i);
Assert.assertEquals(client.getId(), reply.getClientId());
Assert.assertEquals(callId, reply.getCallId());
Assert.assertTrue(reply.isSuccess());
} catch (Exception e) {
LOG.info("hit exception while retrying the same request: " + e);
}
Thread.sleep(100);
}
// check the new leader and make sure the retry did not get committed
Assert.assertEquals(oldLastApplied + 3, cluster.getLeader().getState().getLastAppliedIndex());
client.close();
}
use of org.apache.ratis.protocol.RaftPeer in project alluxio by Alluxio.
the class RaftJournalSystem method resetPriorities.
/**
* Resets RaftPeer priorities.
*
* @throws IOException
*/
public synchronized void resetPriorities() throws IOException {
List<RaftPeer> resetPeers = new ArrayList<>();
final int NEUTRAL_PRIORITY = 1;
for (RaftPeer peer : mRaftGroup.getPeers()) {
resetPeers.add(RaftPeer.newBuilder(peer).setPriority(NEUTRAL_PRIORITY).build());
}
LOG.info("Resetting RaftPeer priorities");
try (RaftClient client = createClient()) {
RaftClientReply reply = client.admin().setConfiguration(resetPeers);
processReply(reply, "failed to reset master priorities to 1");
}
}
use of org.apache.ratis.protocol.RaftPeer 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();
}
}
}
use of org.apache.ratis.protocol.RaftPeer 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;
}
use of org.apache.ratis.protocol.RaftPeer in project alluxio by Alluxio.
the class RaftJournalSystem method startInternal.
@Override
public synchronized void startInternal() throws InterruptedException, IOException {
LOG.info("Initializing Raft Journal System");
InetSocketAddress localAddress = mConf.getLocalAddress();
mPeerId = RaftJournalUtils.getPeerId(localAddress);
List<InetSocketAddress> addresses = mConf.getClusterAddresses();
Set<RaftPeer> peers = addresses.stream().map(addr -> RaftPeer.newBuilder().setId(RaftJournalUtils.getPeerId(addr)).setAddress(addr).build()).collect(Collectors.toSet());
mRaftGroup = RaftGroup.valueOf(RAFT_GROUP_ID, peers);
initServer();
super.registerMetrics();
List<InetSocketAddress> clusterAddresses = mConf.getClusterAddresses();
LOG.info("Starting Raft journal system. Cluster addresses: {}. Local address: {}", clusterAddresses, mConf.getLocalAddress());
long startTime = System.currentTimeMillis();
try {
mServer.start();
} catch (IOException e) {
String errorMessage = ExceptionMessage.FAILED_RAFT_BOOTSTRAP.getMessage(Arrays.toString(clusterAddresses.toArray()), e.getCause() == null ? e : e.getCause().toString());
throw new IOException(errorMessage, e.getCause());
}
LOG.info("Started Raft Journal System in {}ms", System.currentTimeMillis() - startTime);
joinQuorum();
}
Aggregations