solrcloud集群启动管理过程基于源码的分析

基于Solr4.4

先看一下ZK的目录结构
      /collections----solr core的节点,集群的leader节点的选举在该节点下
         --collection1
                  --leader_elect
                            ---shard1
                                  --election
                                    其下是shard1的节点列表
                            ---shard2
                                 ---election
                                         其下是shard2的节点列表
         ---leaders
                    ---shard1
                    ---shard2
      /configs
           --myconf
                其下是solr-home下的配置文件列表
      /live_nodes----当前活动的节点列表
      /overseer_elect/leader---overseer表示集群的状态维护的节点,
           由该节点根据其下queue节点中的信息来更新clusterstate节点内容
           {"id":"90338461809508352-192.168.1.111:8983_solr-n_0000000002"}
      /overseer_elect/election/
                 其下是供elect的节点列表
     /overseer/queue
     /overseer/collection-queue-work
     /overseer/queue-work
     /clusterstate.json---集群的状态信息,每当该节点内容有变化时,
                        所有的节点都会根据本地内存中的clusterstate状态


1、集群启动过程
在这个过程中,主要通过zookeeper client对象,创建用于维护集群状态的Overseer节点(/overseer_elect),
用于Overseer的选举;
Overseer通过后台线程检测DistributeQueue(对该对象的操作是对zookeeper/overseer/queue节点的的读写)的变化
来更新集群状态节点(/clusterstate)的值;
创建相关的节点的(/live_nodes、/clusterstate.json、/aliases.json)watcher来更新集群的状态对象ClusterState。
首先集群启动过程是CoreContainer.load方法开始的
调用ZkController对象的构造函数中初始化SolrZkClient,
   创建solrZkClient对象的过程包括创建ConnectionManager,该对象用于对zookeeper的连接进行管理,
   是作为默认的watcher对象注册的;
   参见DefaultConnectionStrategy.connect,创建了SolrZookeeper客户端连接对象,
   该对象实现了zookeeper客户端接口,
   并利用ZkUpdate回调更新SolrZkClient的成员变量keeper。
   ConnectionManager对连接的管理,参见process接口,
    if (state == KeeperState.SyncConnected)
         //调用listeners回调
          connectionStrategy.connected();
    } else if (state == KeeperState.Expired) {
       //创建新的SolrZookeeper客户端连接对象(实现了zookeeper客户端接口),
          并利用ZkUpdate回调更新SolrZkClient的成员变量keeper
         connectionStrategy.reconnect(zkServerAddress, zkClientTimeout, this, new ZkClientConnectionStrategy.ZkUpdate());
    } else if (state == KeeperState.Disconnected) {
        //调用listeners回调
  connectionStrategy.disconnected();
    }

    在zookeeper连接完成后(ConnectionManager收到连接成功通知),如果connection过期,而重新连接,
    会回调客户端OnReconnect命令接口,进行重新连接的过程
     参见ZkController构造函数,
       a、创建zkClient
  zkClient = new SolrZkClient(zkServerAddress, zkClientTimeout, zkClientConnectTimeout,
        // on reconnect, reload cloud info
           new OnReconnect() {
            @Override
             public void command() {
         //关键步骤如下:
       //创建用于维护集群状态的对象Overseer
       //overseer的节点
              ZkController.this.overseer = new Overseer(shardHandler, adminPath, zkStateReader);
       ElectionContext context = new OverseerElectionContext(zkClient, overseer, getNodeName());
       //leader选举,基本原理是选举"/overseer_elect/election下seq最小的节点即为leader",
         每个节点watch并它次小节点的变化,
       //如果有变化通知,则checkIfIamLeader,
              //如果当前节点上最小的,那么就runIamLeaderProcess,
          更新"/overseer_elect/leader"下的节点信息,
       //并调用Overseer.start(id)来启动两个后台线程,
           ClusterStateUpdater(在process中更新/clusterstate.json节点的值)
          和OverseerCollectionProcessor(处理管理collection的请求)
       //这两个线程的职位分别如下,
        //ClusterStateUpdater负责从queue获取任务,设置到queue-work中,进行处理工作;
        //OverseerCollectionProcessor负责collection相关的Collection-queue-work的处理工作
       overseerElector.joinElection(context, true);
       //创建集群状态节点/clusterstate.json的watcher,监听该节点的变化(zkClient.exists(CLUSTER_STATE, new Watcher())),
       //在watcher的process方法中,读取/clusterstate.json、/live_nodes节点数据到ZkStateReader.clusterState中
       //创建/live_nodes节点下的watcher,在process方法中更新clusterState;
       //创建/aliases.json节点的watcher,在process方法中更新clusterState;
       //根据集群的状态clusterstate,更新ClusterState对象(创建Slice(Range)....)
                zkStateReader.createClusterStateWatchersAndUpdate();
              //创建/live_nodes
       createEphemeralLiveNode();
      ......
      }
       b、zkClient创建完成后,利用该SolrZkClient,创建两个分布式队列DistributedQueue,queue、collection-queue,
          创建用于选举leader的LeaderElector对象,
          创建Zookeeper状态读取器ZkStateReader,
          初始化init
          该过程同上面的onReconnect的步骤是类似的,这里不再阐述。

2、加载core--创建collection
  以上启动过程完成后,会异步加载core
a、发布core信息到zookeeper中,使得更新cloudstate状态 
  CoreContainer.preRegisterInZk
   --ZkController.preRegister(CoreDescriptor)
        ---ZkController.publish(CoreDescriptor,String,Boolean)
    --- overseerJobQueue.offer(ZkStateReader.toJSON(m));//放进queue中
b、zookeeper中创建/collections节点
   --CoreContainer.create(CoreDescriptor)
      --ZkContainer.createFromZk()
         --ZkContainer.createCollectionZkNode(CloudDescriptor)//创建/collections节点
c、zookeeper中进行leader的选举/collections/collection1/leader_elect/shard1/election
    ----CoreContainer.registerCore(p.isTransient(), name, c, false);
          --ZkController.registerInZk(ZkCore)
        --zkController.joinElection
        //创建/collections/collection1/leader_elect/shard1/election节点,进行leader选举,
        //选举算法和overseer是一样的,都是seqno最小的为leader;leader选举完成后,
            通过发送到queue中,更新cloudstate状态
     ---ShardLeaderElectionContext(init)
     ---LeaderElector.checkIfIamLeader
         --LeaderElector.runIamLeaderProcess
            ---ShardLeaderElectionContext.runLeaderProcess
                //放进queue中
               ---Overseer.getInQueue(zkClient).offer(ZkStateReader.toJSON(m));

 

你可能感兴趣的:(集群,Solr)