现在的工程就是在源码的层面进行改动,之前因为一个问题出现了集群假死的状态。所以才深入的去分析了,源码的集群同步的状态。
简述
首先需要明白,类似于solr使用的是zookeeper来进行集群状态的同步。等于是使用了三方件实现集群状态的维护。但是要明白elasticsearch没有用到zookeeper,etcd来管理节点的主备逻辑。
所以,集群状态同步是怎么完成的呢。
推荐看一下这篇文章 ELASTICSEARCH 机制和架构 这个网站写了很多elasticsearch相关的分析,对我的启发不小。我也只是在他的文章的期初上做点发挥。
节点类型
不说那么复杂,简单关注两个节点类型。
master节点
首先,在elasticsearch.yml文件中只有配置了node.master: true ,本节点才能保证可以被选为主节点。
如果自己做源码分析,最好是将master和data节点分开,如果可以就自己多打点日志。或者开启debug日志,可以简单跟踪一下流程。单节点调试的话,因为很多流程是异步的,所以不一定能分离的很清楚。
其次,主节点主要就是负责集群状态的下发。关注ClusterService类。
状态更新的入口,至于怎么走到这个入口的慢慢分析:
void runTasks(TaskInputs taskInputs) {
...
TaskOutputs taskOutputs = calculateTaskOutputs(taskInputs, previousClusterState, startTimeNS); // 第一个重点,主节点计算metadata,比如创建index之后的集群状态。
taskOutputs.notifyFailedTasks();
if (taskOutputs.clusterStateUnchanged()) {
taskOutputs.notifySuccessfulTasksOnUnchangedClusterState();
TimeValue executionTime = TimeValue.timeValueMillis(Math.max(0, TimeValue.nsecToMSec(currentTimeInNanos() - startTimeNS)));
logger.debug("processing [{}]: took [{}] no change in cluster_state", taskInputs.summary, executionTime);
warnAboutSlowTaskIfNeeded(executionTime, taskInputs.summary);
} else {
ClusterState newClusterState = taskOutputs.newClusterState;
if (logger.isTraceEnabled()) {
logger.trace("cluster state updated, source [{}]\n{}", taskInputs.summary, newClusterState);
} else if (logger.isDebugEnabled()) {
logger.debug("cluster state updated, version [{}], source [{}]", newClusterState.version(), taskInputs.summary);
}
try {
publishAndApplyChanges(taskInputs, taskOutputs); // 看名字就知道什么意思了,将集群状态下发。
TimeValue executionTime = TimeValue.timeValueMillis(Math.max(0, TimeValue.nsecToMSec(currentTimeInNanos() - startTimeNS)));
logger.debug("processing [{}]: took [{}] done applying updated cluster_state (version: {}, uuid: {})", taskInputs.summary,
executionTime, newClusterState.version(), newClusterState.stateUUID());
warnAboutSlowTaskIfNeeded(executionTime, taskInputs.summary);
} catch (Exception e) {
TimeValue executionTime = TimeValue.timeValueMillis(Math.max(0, TimeValue.nsecToMSec(currentTimeInNanos() - startTimeNS)));
final long version = newClusterState.version();
final String stateUUID = newClusterState.stateUUID();
final String fullState = newClusterState.toString();
logger.warn(
(Supplier<?>) () -> new ParameterizedMessage(
"failed to apply updated cluster state in [{}]:\nversion [{}], uuid [{}], source [{}]\n{}",
executionTime,
version,
stateUUID,
taskInputs.summary,
fullState),
e);
// TODO: do we want to call updateTask.onFailu