@Override public void contextInitialized(ServletContextEvent sce) { this.servletContext = sce.getServletContext(); RaftContext context = new RaftContext( this.getServerStateManager(), this.getStateMachine(), this.getParameters(), this, this.getLoggerFactory(), new HttpRpcClientFactory()); this.servletContext.setAttribute(JRAFT_MESSAGE_SENDER, RaftConsensus.run(context)); }
public RaftServer(RaftContext context){ this.id = context.getServerStateManager().getServerId(); this.state = context.getServerStateManager().readState(); this.logStore = context.getServerStateManager().loadLogStore(); this.config = context.getServerStateManager().loadClusterConfiguration(); this.stateMachine = context.getStateMachine(); this.votesGranted = 0; this.leader = -1; this.snapshotInProgress = new AtomicInteger(0); this.context = context; this.logger = context.getLoggerFactory().getLogger(this.getClass()); this.random = new Random(Calendar.getInstance().getTimeInMillis()); this.electionTimeoutTask = new Callable<Void>(){
private void restartElectionTimer(){ // don't start the election timer while this server is still catching up the logs if(this.catchingUp){ return; } if(this.scheduledElection != null){ this.scheduledElection.cancel(false); } RaftParameters parameters = this.context.getRaftParameters(); int electionTimeout = parameters.getElectionTimeoutLowerBound() + this.random.nextInt(parameters.getElectionTimeoutUpperBound() - parameters.getElectionTimeoutLowerBound() + 1); this.scheduledElection = this.context.getScheduledExecutor().schedule(this.electionTimeoutTask, electionTimeout, TimeUnit.MILLISECONDS); }
public PeerServer(ClusterServer server, RaftContext context, final Consumer<PeerServer> heartbeatConsumer){ this.clusterConfig = server; this.rpcClient = context.getRpcClientFactory().createRpcClient(server.getEndpoint()); this.busyFlag = new AtomicInteger(0); this.pendingCommitFlag = new AtomicInteger(0); this.heartbeatInterval = this.currentHeartbeatInterval = context.getRaftParameters().getHeartbeatInterval(); this.maxHeartbeatInterval = context.getRaftParameters().getMaxHeartbeatInterval(); this.rpcBackoffInterval = context.getRaftParameters().getRpcFailureBackoff(); this.heartbeatTask = null; this.snapshotSyncContext = null; this.nextLogIndex = 1; this.matchedIndex = 0; this.heartbeatEnabled = false; this.executor = context.getScheduledExecutor(); PeerServer self = this; this.heartbeatTimeoutHandler = new Callable<Void>(){ @Override public Void call() throws Exception { heartbeatConsumer.accept(self); return null; }}; }
public static RaftMessageSender run(RaftContext context){ if(context == null){ throw new IllegalArgumentException("context cannot be null"); } RaftServer server = new RaftServer(context); RaftMessageSender messageSender = server.createMessageSender(); context.getStateMachine().start(messageSender); context.getRpcListener().startListening(server); return messageSender; } }
private boolean updateTerm(long term){ if(term > this.state.getTerm()){ this.state.setTerm(term); this.state.setVotedFor(-1); this.electionCompleted = false; this.votesGranted = 0; this.votedServers.clear(); this.context.getServerStateManager().persistState(this.state); this.becomeFollower(); return true; } return false; }
private void enableHeartbeatForPeer(PeerServer peer){ peer.enableHeartbeat(true); peer.resumeHeartbeatingSpeed(); peer.setHeartbeatTask(this.context.getScheduledExecutor().schedule(peer.getHeartbeartHandler(), peer.getCurrentHeartbeatInterval(), TimeUnit.MILLISECONDS)); }
private void requestVote(){ // vote for self this.logger.info("requestVote started with term %d", this.state.getTerm()); this.state.setVotedFor(this.id); this.context.getServerStateManager().persistState(this.state); this.votesGranted += 1; this.votedServers.add(this.id); // this is the only server? if(this.votesGranted > (this.peers.size() + 1) / 2){ this.electionCompleted = true; this.becomeLeader(); return; } for(PeerServer peer : this.peers.values()){ RaftRequestMessage request = new RaftRequestMessage(); request.setMessageType(RaftMessageType.RequestVoteRequest); request.setDestination(peer.getId()); request.setSource(this.id); request.setLastLogIndex(this.logStore.getFirstAvailableIndex() - 1); request.setLastLogTerm(this.termForLastLog(this.logStore.getFirstAvailableIndex() - 1)); request.setTerm(this.state.getTerm()); this.logger.debug("send %s to server %d with term %d", RaftMessageType.RequestVoteRequest.toString(), peer.getId(), this.state.getTerm()); peer.SendRequest(request).whenCompleteAsync((RaftResponseMessage response, Throwable error) -> { handlePeerResponse(response, error); }, this.context.getScheduledExecutor()); } }
rpcClient = this.server.context.getRpcClientFactory().createRpcClient(leader.getEndpoint()); this.rpcClients.put(leaderId, rpcClient); result.complete(response.isAccepted()); }, this.server.context.getScheduledExecutor());
private int getSnapshotSyncBlockSize(){ int blockSize = this.context.getRaftParameters().getSnapshotBlockSize(); return blockSize == 0 ? DEFAULT_SNAPSHOT_SYNC_BLOCK_SIZE : blockSize; }
public static RaftMessageSender run(RaftContext context){ if(context == null){ throw new IllegalArgumentException("context cannot be null"); } RaftServer server = new RaftServer(context); context.getRpcListener().startListening(server); return server.createMessageSender(); } }
public PeerServer(ClusterServer server, RaftContext context, final Consumer<PeerServer> heartbeatConsumer){ this.clusterConfig = server; this.rpcClient = context.getRpcClientFactory().createRpcClient(server.getEndpoint()); this.busyFlag = new AtomicInteger(0); this.pendingCommitFlag = new AtomicInteger(0); this.heartbeatInterval = this.currentHeartbeatInterval = context.getRaftParameters().getHeartbeatInterval(); this.maxHeartbeatInterval = context.getRaftParameters().getMaxHeartbeatInterval(); this.rpcBackoffInterval = context.getRaftParameters().getRpcFailureBackoff(); this.heartbeatTask = null; this.snapshotSyncContext = null; this.nextLogIndex = 1; this.matchedIndex = 0; this.heartbeatEnabled = false; this.executor = context.getScheduledExecutor(); PeerServer self = this; this.heartbeatTimeoutHandler = new Callable<Void>(){ @Override public Void call() throws Exception { heartbeatConsumer.accept(self); return null; }}; }
private boolean updateTerm(long term){ if(term > this.state.getTerm()){ this.state.setTerm(term); this.state.setVotedFor(-1); this.electionCompleted = false; this.votesGranted = 0; this.votesResponded = 0; this.context.getServerStateManager().persistState(this.state); this.becomeFollower(); return true; } return false; }
private void enableHeartbeatForPeer(PeerServer peer){ peer.enableHeartbeat(true); peer.resumeHeartbeatingSpeed(); peer.setHeartbeatTask(this.context.getScheduledExecutor().schedule(peer.getHeartbeartHandler(), peer.getCurrentHeartbeatInterval(), TimeUnit.MILLISECONDS)); }
private void requestVote(){ // vote for self this.logger.info("requestVote started with term %d", this.state.getTerm()); this.state.setVotedFor(this.id); this.context.getServerStateManager().persistState(this.state); this.votesGranted += 1; this.votesResponded += 1; // this is the only server? if(this.votesGranted > (this.peers.size() + 1) / 2){ this.electionCompleted = true; this.becomeLeader(); return; } for(PeerServer peer : this.peers.values()){ RaftRequestMessage request = new RaftRequestMessage(); request.setMessageType(RaftMessageType.RequestVoteRequest); request.setDestination(peer.getId()); request.setSource(this.id); request.setLastLogIndex(this.logStore.getFirstAvailableIndex() - 1); request.setLastLogTerm(this.termForLastLog(this.logStore.getFirstAvailableIndex() - 1)); request.setTerm(this.state.getTerm()); this.logger.debug("send %s to server %d with term %d", RaftMessageType.RequestVoteRequest.toString(), peer.getId(), this.state.getTerm()); peer.SendRequest(request).whenCompleteAsync((RaftResponseMessage response, Throwable error) -> { handlePeerResponse(response, error); }, this.context.getScheduledExecutor()); } }
rpcClient = this.server.context.getRpcClientFactory().createRpcClient(leader.getEndpoint()); this.rpcClients.put(leaderId, rpcClient); result.complete(response.isAccepted()); }, this.server.context.getScheduledExecutor());
public static RaftMessageSender run(RaftContext context){ if(context == null){ throw new IllegalArgumentException("context cannot be null"); } RaftServer server = new RaftServer(context); RaftMessageSender messageSender = server.createMessageSender(); context.getStateMachine().start(messageSender); context.getRpcListener().startListening(server); return messageSender; } }
private int getSnapshotSyncBlockSize(){ int blockSize = this.context.getRaftParameters().getSnapshotBlockSize(); return blockSize == 0 ? DEFAULT_SNAPSHOT_SYNC_BLOCK_SIZE : blockSize; }
private void restartElectionTimer(){ // don't start the election timer while this server is still catching up the logs if(this.catchingUp){ return; } if(this.scheduledElection != null){ this.scheduledElection.cancel(false); } RaftParameters parameters = this.context.getRaftParameters(); int electionTimeout = parameters.getElectionTimeoutLowerBound() + this.random.nextInt(parameters.getElectionTimeoutUpperBound() - parameters.getElectionTimeoutLowerBound() + 1); this.scheduledElection = this.context.getScheduledExecutor().schedule(this.electionTimeoutTask, electionTimeout, TimeUnit.MILLISECONDS); }
public PeerServer(ClusterServer server, RaftContext context, final Consumer<PeerServer> heartbeatConsumer){ this.clusterConfig = server; this.rpcClient = context.getRpcClientFactory().createRpcClient(server.getEndpoint()); this.busyFlag = new AtomicInteger(0); this.pendingCommitFlag = new AtomicInteger(0); this.heartbeatInterval = this.currentHeartbeatInterval = context.getRaftParameters().getHeartbeatInterval(); this.maxHeartbeatInterval = context.getRaftParameters().getMaxHeartbeatInterval(); this.rpcBackoffInterval = context.getRaftParameters().getRpcFailureBackoff(); this.heartbeatTask = null; this.snapshotSyncContext = null; this.nextLogIndex = 1; this.matchedIndex = 0; this.heartbeatEnabled = false; this.executor = context.getScheduledExecutor(); PeerServer self = this; this.heartbeatTimeoutHandler = new Callable<Void>(){ @Override public Void call() throws Exception { heartbeatConsumer.accept(self); return null; }}; }