elasticsearch源码分析---discovery模块

来源:互联网 发布:gif制作软件中文版 编辑:程序博客网 时间:2024/05/17 22:00

根据guice的注册绑定机制,discovery的绑定顺序是这样的:

InternalNode中添加DiscoveryModule:

modules.add(new DiscoveryModule(settings));

DiscoveryModule中创建了LocalDiscoveryModule(不分析)或者ZenDiscoveryModule:

  public Iterable<? extends Module> spawnModules() {        Class<? extends Module> defaultDiscoveryModule;        if (DiscoveryNode.localNode(settings)) {            defaultDiscoveryModule = LocalDiscoveryModule.class;        } else {            defaultDiscoveryModule = ZenDiscoveryModule.class;        }        return ImmutableList.of(Modules.createModule(settings.getAsClass(DISCOVERY_TYPE_KEY, defaultDiscoveryModule, "org.elasticsearch.discovery.", "DiscoveryModule"), settings));    }

ZenDiscoveryModule中将Discovery Class绑定到了ZenDiscovery Class

  protected void bindDiscovery() {        bind(Discovery.class).to(ZenDiscovery.class).asEagerSingleton();    }

InternalNode中启动DiscoveryService:

DiscoveryService discoService = injector.getInstance(DiscoveryService.class).start();

DiscoveryService最终绑定到哪里呢?在ZenDiscovery Class上:

   @Inject    public DiscoveryService(Settings settings, Discovery discovery) {        super(settings);        this.discovery = discovery;        this.initialStateTimeout = componentSettings.getAsTime("initial_state_timeout", TimeValue.timeValueSeconds(30));    }
看,是在Discovery这个类中,因此最终落在ZenDiscovery上。

DiscoveryService启动过程就是启动ZenDiscovery,如下:

 protected void doStart() throws ElasticsearchException {        initialStateListener = new InitialStateListener();        discovery.addListener(initialStateListener);        discovery.start();        logger.info(discovery.nodeDescription());    }

ZenDiscovery除了共用transport等其他模块外,还有以下几个辅助类:

        this.electMaster = new ElectMasterService(settings);        nodeSettingsService.addListener(new ApplySettings());        this.masterFD = new MasterFaultDetection(settings, threadPool, transportService, this);        this.masterFD.addListener(new MasterNodeFailureListener());        this.nodesFD = new NodesFaultDetection(settings, threadPool, transportService);        this.nodesFD.addListener(new NodeFailureListener());        this.publishClusterState = new PublishClusterStateAction(settings, transportService, this, new NewClusterStateListener(), discoverySettings);        this.pingService.setNodesProvider(this);        this.membership = new MembershipAction(settings, transportService, this, new MembershipListener());
NodeFaultDetection:检测其他集群节点的状态(master节点使用)

在其中维护了一张Node和NodeFD的映射关系,注册了PingRequestHandler和FDConnectionListener(根据setting设定),以及处理逻辑。

private final ConcurrentMap<DiscoveryNode, NodeFD> nodesFD = newConcurrentMap();
updateNodes用来更新以上数据结构:

public void updateNodes(DiscoveryNodes nodes) {        DiscoveryNodes prevNodes = latestNodes;        this.latestNodes = nodes;        if (!running) {            return;        }        DiscoveryNodes.Delta delta = nodes.delta(prevNodes);        for (DiscoveryNode newNode : delta.addedNodes()) {            if (newNode.id().equals(nodes.localNodeId())) {                // no need to monitor the local node                continue;            }            if (!nodesFD.containsKey(newNode)) {                nodesFD.put(newNode, new NodeFD());                threadPool.schedule(pingInterval, ThreadPool.Names.SAME, new SendPingRequest(newNode));            }        }        for (DiscoveryNode removedNode : delta.removedNodes()) {            nodesFD.remove(removedNode);        }    }

通过比较当前集群中nodes和上一个记录的集群中nodes来确定新加入或者删除的node,本地节点无需监控。最终在nodesFD中的节点就是当前需要检测的节点。

MasterNodeDetection:检测master节点的状态(非master节点使用)

ElectMasterService:选举master节点。

现在来看一下ZenDiscovery的启动流程:

  protected void doStart() throws ElasticsearchException {        Map<String, String> nodeAttributes = discoveryNodeService.buildAttributes();        // note, we rely on the fact that its a new id each time we start, see FD and "kill -9" handling        final String nodeId = DiscoveryService.generateNodeId(settings);        localNode = new DiscoveryNode(settings.get("name"), nodeId, transportService.boundAddress().publishAddress(), nodeAttributes, version);        latestDiscoNodes = new DiscoveryNodes.Builder().put(localNode).localNodeId(localNode.id()).build();        nodesFD.updateNodes(latestDiscoNodes);        pingService.start();        // do the join on a different thread, the DiscoveryService waits for 30s anyhow till it is discovered        asyncJoinCluster();    }

NodeFaultDetection实例nodesFD会更新维护的map结构(新节点加入了,或许这个时刻有些节点也被删除了,获取新的delta关系)

然后启动加入本地节点的流程asyncJoinCluster,最终调用到innerJoinCluster:

大致逻辑是先findMaster,如果是master是自己,做标识并启动NodesFaultDetection来监控其余节点,发布自己是master节点的消息,如果不是自己,循环连接master节点,直到连接成功,向master节点发送要求加入cluster的消息,启动MasterFaultDetection,来监控master节点的状态。

findMaster会确定master节点:对各个节点发送ping信息,根据返回的节点属性还获取可能的master节点(过滤client节点,过滤data但是不是master的节点)。判断当前获取的具有master节点资格的数据是否符合最小master节点数目,如果不符合,说明还有节点没有启动,返回null,继续等待节点启动直到符合最小master节点数目位置。下边出现了两种情况:如果在节点的ping信息返回中含有master节点,则在这些ping信息中包含的master节点中确定一个master节点返回,如果在节点的ping信息中无master节点,则在具有master节点资格的节点中选举一个作为master节点。选举策略有ElectMasterService负责。





0 0