找到RaftCore类,该类被@Component标志,并且有个方法被@PostConstruct所标注:
@PostConstruct
public void init() throws Exception {
这里有几个核心概念或组件:
1.peer:代表每台nocas机器,记录着一台server的投票相关的元数据信息,比如本机的ip,投票给谁(votefor),AtomicLong类型的term,记录本地服务第几次发起的投票,状体(leader/follower),leader选举间隔时间等。
2.peers:是个RaftPeerSet类型,实际上记录了整个集群所有peer的信息。
3.notifier:一个线程,用作事件通知。
下面看初始化过程:
@PostConstruct
public void init() throws Exception {
Loggers.RAFT.info("initializing Raft sub-system");
//事件通知线程
executor.submit(notifier);
long start = System.currentTimeMillis();
//从磁盘中加载Datum数据到datums内存中,用于数据恢复
//Datum:kv对
//datums:ConcurrentMap<String, Datum>
raftStore.loadDatums(notifier, datums);
//loadMeta():加载nacos_home/data/naming/meta.properties文件,默认不存在term这个key,取默认值0
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));
//每500ms调度一下该线程,用来判断是否需要选举leader
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);
}
前面先不管,这里最重要的是:GlobalExecutor.registerMasterElection(new MasterElection()); 每过500ms启动一次该选举线程:
public static void registerMasterElection(Runnable runnable) {
//TICK_PERIOD_MS:500
executorService.scheduleAtFixedRate(runnable, 0, TICK_PERIOD_MS, TimeUnit.MILLISECONDS);
}
传给该方法的MasterElection是个线程,该行实际上是使用一个线程的执行器调起该线程,直接看MasterElection类:
public class MasterElection implements Runnable {
@Override
public void run() {