NOTE: Mostly based on Solr 7.2
首先来看下Solr官方对Overseer类的注解:
/**
* Cluster leader. Responsible for processing state updates, node assignments, creating/deleting
* collections, shards, replicas and setting various properties.
*/
字面上的意思是,Overseer是集群的领导者,负责处理集群状态变更,节点任务,创建删除索引、分片和副本,并支持设置多种属性。Overseer角色对于Solr集群的重要性不言而喻。
// overseer not responsible for closing reader
public Overseer(ShardHandler shardHandler, UpdateShardHandler updateShardHandler, String adminPath,
final ZkStateReader reader, ZkController zkController, CloudConfig config) throws KeeperException, InterruptedException {
this.reader = reader;
this.shardHandler = shardHandler;
this.updateShardHandler = updateShardHandler;
this.adminPath = adminPath;
this.zkController = zkController;
this.stats = new Stats();
this.config = config;
}
这是Overseer唯一的构造函数,在ZKController类中被唯一调用。ZKController的定位是用来Handle ZooKeeper interactions。
Overseer中定义了一个子类ClusterStateUpdater,顾名思义,是用来更新集群状态的。子类ClusterStateUpdater共计约400行代码,几乎占用整个Overseer类的一半篇幅,从代码量上可以想见这个类的重要性。
来,贴上完整的代码看看。重要的地方以 “ // —— 中文注解 ” 的形式标出。
private class ClusterStateUpdater implements Runnable, Closeable {
private final ZkStateReader reader;
private final SolrZkClient zkClient;
private final String myId;
//queue where everybody can throw tasks
private final ZkDistributedQueue stateUpdateQueue; // —— 任何人都可以往里面丢任务的通用队列,包括状态变更,创建索引等任务。
//TODO remove in 9.0, we do not push message into this queue anymore
//Internal queue where overseer stores events that have not yet been published into cloudstate
//If Overseer dies while extracting the main queue a new overseer will start from this queue
private final ZkDistributedQueue workQueue; // —— 这个workQueue在Solr 9.0将会被移除,这里的作用仅仅是replay队列/overseer/queue-work里面的任务one by one。
// Internal map which holds the information about running tasks.
private final DistributedMap runningMap;
// Internal map which holds the information about successfully completed tasks.
private final DistributedMap completedMap;
// Internal map which holds the information about failed tasks.
private final DistributedMap failureMap;
private final Stats zkStats;
private boolean isClosed = false;
// —— ClusterStateUpdater构造函数
public ClusterStateUpdater(final ZkStateReader reader, final String myId, Stats zkStats) {
this.zkClient = reader.getZkClient();
this.zkStats = zkStats;
this.stateUpdateQueue = getStateUpdateQueue(zkClient, zkStats);
this.workQueue = getInternalWorkQueue(zkClient, zkStats);
this.failureMap = getFailureMap(zkClient);
this.runningMap = getRunningMap(zkClient);
this.completedMap = getCompletedMap(zkClient);
this.myId = myId;
this.reader = reader;
}
public Stats getStateUpdateQueueStats() {
return stateUpdateQueue.getZkStats();
}
public Stats getWorkQueueStats() {
return workQueue.getZkStats();
}
@Override
public void run() { // —— 一大波僵尸正在靠近~BOOM~~~
LeaderStatus isLeader = amILeader();
while (isLeade