sequence
This article mainly studies the MasterElection of NacOS RaftCore
RaftCore
Nacos – 1.1.3 / naming/SRC/main/Java/com/alibaba/nacos/naming/consistency/persistent/raft/RaftCore Java
@Component
public class RaftCore {
//......
@PostConstruct
public void init() throws Exception {
Loggers.RAFT.info("initializing Raft sub-system");
executor.submit(notifier);
long start = System.currentTimeMillis();
raftStore.loadDatums(notifier, datums);
setTerm(NumberUtils.toLong(raftStore.loadMeta().getProperty("term"), 0L));
Loggers.RAFT.info("cache loaded, datum count: {}, current term: {}", datums.size(), peers.getTerm());
while (true) {
if (notifier.tasks.size() <= 0) {
break;
}
Thread.sleep(1000L);
}
initialized = true;
Loggers.RAFT.info("finish to load data from disk, cost: {} ms.", (System.currentTimeMillis() - start));
GlobalExecutor.registerMasterElection(new MasterElection());
GlobalExecutor.registerHeartbeat(new HeartBeat());
Loggers.RAFT.info("timer started: leader timeout ms: {}, heart-beat timeout ms: {}", GlobalExecutor.LEADER_TIMEOUT_MS, GlobalExecutor.HEARTBEAT_INTERVAL_MS); } / /... }Copy the code
- RaftCore init method through GlobalExecutor. RegisterMasterElection (new MasterElection ()) registered MasterElection
GlobalExecutor
Nacos – 1.1.3 / naming/SRC/main/Java/com/alibaba/nacos/naming/misc/GlobalExecutor Java
public class GlobalExecutor { //...... public static final long TICK_PERIOD_MS = TimeUnit.MILLISECONDS.toMillis(500L); public static void registerMasterElection(Runnable runnable) { executorService.scheduleAtFixedRate(runnable, 0, TICK_PERIOD_MS, TimeUnit.MILLISECONDS); } / /... }Copy the code
- The registerMasterElection method dispatches runnable every TICK_PERIOD_MS millisecond
MasterElection
Nacos – 1.1.3 / naming/SRC/main/Java/com/alibaba/nacos/naming/consistency/persistent/raft/RaftCore Java
public class MasterElection implements Runnable {
@Override
public void run() {
try {
if(! peers.isReady()) {return;
}
RaftPeer local = peers.local();
local.leaderDueMs -= GlobalExecutor.TICK_PERIOD_MS;
if (local.leaderDueMs > 0) {
return;
}
// reset timeout
local.resetLeaderDue();
local.resetHeartbeatDue();
sendVote();
} catch (Exception e) {
Loggers.RAFT.warn("[RAFT] error while master election {}", e);
}
}
public void sendVote() {
RaftPeer local = peers.get(NetUtils.localServer());
Loggers.RAFT.info("leader timeout, start voting,leader: {}, term: {}",
JSON.toJSONString(getLeader()), local.term);
peers.reset();
local.term.incrementAndGet();
local.voteFor = local.ip;
local.state = RaftPeer.State.CANDIDATE;
Map<String, String> params = new HashMap<>(1);
params.put("vote", JSON.toJSONString(local));
for (final String server : peers.allServersWithoutMySelf()) {
final String url = buildURL(server, API_VOTE);
try {
HttpClient.asyncHttpPost(url, null, params, new AsyncCompletionHandler<Integer>() {
@Override
public Integer onCompleted(Response response) throws Exception {
if(response.getStatusCode() ! = HttpURLConnection.HTTP_OK) { Loggers.RAFT.error("NACOS-RAFT vote failed: {}, url: {}", response.getResponseBody(), url);
return 1;
}
RaftPeer peer = JSON.parseObject(response.getResponseBody(), RaftPeer.class);
Loggers.RAFT.info("received approve from peer: {}", JSON.toJSONString(peer));
peers.decideLeader(peer);
return0; }}); } catch (Exception e) { Loggers.RAFT.warn("error while sending vote to server: {}", server); }}}}Copy the code
- MasterElection implements the Runnable method, whose run method starts the election when peers are all ready and local.leaderDueMs minus TICK_PERIOD_MS is less than or equal to 0. It first resetLeaderDue and resetHeartbeatDue and then executes the sendVote method; The sendVote method first resets peers, increments term of localPeer, sets voteFor to itself, and then updates state to raftpeer-.state.candidate, The traversal peers. AllServersWithoutMySelf (), will own asynchronous post that information to the other peer; Execute peers. DecideLeader (peer) if the other peers return success and return 1, otherwise return 0
summary
RaftCore init method through GlobalExecutor. RegisterMasterElection (new MasterElection ()) registered MasterElection; The registerMasterElection method is scheduled every TICK_PERIOD_MS ms; MasterElection implements the Runnable method, whose run method starts the election when peers are all ready and local.leaderDueMs minus TICK_PERIOD_MS is less than or equal to 0. It first resetLeaderDue and resetHeartbeatDue and then executes the sendVote method
doc
- RaftCore