elasticsearch 代码分析之modules and services

最近需要研究搜索的集群。由于大脑日渐萎缩,只好把代码记下来以供参考,好久没在csdn上写东西了,呵呵。

elasticsearch是一个基于lucene的搜索集群,关于lucene的介绍有如下参考:

Annotated-Lucene源码剖析中文版
Architecture and Implementation of Apache Lucene
Lucene 源码分析

elasticsesarch作为一个封装lucene的开源项目,根据CAP理论在牺牲一致性(C)的,保证了数据的分布(P)和可达(A)。当然数据是有最终一直性的。
参考资料:solar VS elk http://solr-vs-elasticsearch.com/

关于elasticsearch如何保证cap我们以后会深入理解。

本章先告诉大家如何看elasticsearch源代码:
如果你熟悉AOP 或者spring framework, 就会发现elasticsearch源代码是按照模块组织的。只不过用了另外一个开源框架Guice。guice如何实现依赖注入的参考:
http://malsup.com/jquery/media/guice.pdf

扯了很多终于可以讲主题了:
elasticsearch的官网:https://www.elastic.co/blog/found-elasticsearch-internals列出了所有elasticsearch 的模块。今天就已discovery module为例看看elasticsearch是如何注册并使用这一service的。

node.class代表elasticsearch的一个节点,他包含了启动一个节点的所有服务:`

Node(Settings preparedSettings, Version version, Collection> classpathPlugins) {
        final Settings pSettings = settingsBuilder().put(preparedSettings)
                .put(Client.CLIENT_TYPE_SETTING, CLIENT_TYPE).build();
        Environment tmpEnv = InternalSettingsPreparer.prepareEnvironment(pSettings, null);
        Settings tmpSettings = TribeService.processSettings(tmpEnv.settings());

        ESLogger logger = Loggers.getLogger(Node.class, tmpSettings.get("name"));
        logger.info("version[{}], pid[{}], build[{}/{}]", version, JvmInfo.jvmInfo().pid(), Build.CURRENT.hashShort(), Build.CURRENT.timestamp());

        logger.info("initializing ...");

        if (logger.isDebugEnabled()) {
            logger.debug("using config [{}], data [{}], logs [{}], plugins [{}]",
                tmpEnv.configFile(), Arrays.toString(tmpEnv.dataFiles()), tmpEnv.logsFile(), tmpEnv.pluginsFile());
        }

        this.pluginsService = new PluginsService(tmpSettings, tmpEnv.pluginsFile(), classpathPlugins);
        this.settings = pluginsService.updatedSettings();
        // create the environment based on the finalized (processed) view of the settings
        this.environment = new Environment(this.settings());

        final NodeEnvironment nodeEnvironment;
        try {
            nodeEnvironment = new NodeEnvironment(this.settings, this.environment);
        } catch (IOException ex) {
            throw new IllegalStateException("Failed to created node environment", ex);
        }

        final ThreadPool threadPool = new ThreadPool(settings);

        boolean success = false;
        try {
            ModulesBuilder modules = new ModulesBuilder();
            modules.add(new Version.Module(version));
            modules.add(new CircuitBreakerModule(settings));
            // plugin modules must be added here, before others or we can get crazy injection errors...
            for (Module pluginModule : pluginsService.nodeModules()) {
                modules.add(pluginModule);
            }
            modules.add(new PluginsModule(pluginsService));
            modules.add(new SettingsModule(this.settings));
            modules.add(new NodeModule(this));
            modules.add(new NetworkModule());
            modules.add(new ScriptModule(this.settings));
            modules.add(new EnvironmentModule(environment));
            modules.add(new NodeEnvironmentModule(nodeEnvironment));
            modules.add(new ClusterNameModule(this.settings));
            modules.add(new ThreadPoolModule(threadPool));
            modules.add(new DiscoveryModule(this.settings));
            modules.add(new ClusterModule(this.settings));
            modules.add(new RestModule(this.settings));
            modules.add(new TransportModule(settings));
            if (settings.getAsBoolean(HTTP_ENABLED, true)) {
                modules.add(new HttpServerModule(settings));
            }
            modules.add(new IndicesModule(settings));
            modules.add(new SearchModule(settings));
            modules.add(new ActionModule(false));
            modules.add(new MonitorModule(settings));
            modules.add(new GatewayModule(settings));
            modules.add(new NodeClientModule());
            modules.add(new ShapeModule());
            modules.add(new PercolatorModule());
            modules.add(new ResourceWatcherModule());
            modules.add(new RepositoriesModule());
            modules.add(new TribeModule());


            pluginsService.processModules(modules);

            injector = modules.createInjector();

            client = injector.getInstance(Client.class);
            threadPool.setNodeSettingsService(injector.getInstance(NodeSettingsService.class));
            success = true;
        } finally {
            if (!success) {
                nodeEnvironment.close();
                ThreadPool.terminate(threadPool, 10, TimeUnit.SECONDS);
            }
        }

        logger.info("initialized");
    }

通过它的构造函数可以清楚的看到elasticsearch加载了那些模块

modules.add(new DiscoveryModule(this.settings));

说明elasticsearch加载了DiscoveryModule。
elasticsearch 代码分析之modules and services_第1张图片

每个discovery module 包含了不同的多个Discovery模块,每个discovery模块都是先了自己的publishi方法,通过广播的形式将master node接受到的node change event时间告诉其他的监听器。

其中最重要的就是 ZenDiscovery,它负责在局域网内通过多播(multi-broadcast)或者单播的形式发现其他节点并将之纳入cluster中。

第一次写关于开源项目研究的笔记,不尽之处希望大家多多指正。
有想一起研讨的也多多给我留言。

你可能感兴趣的:(搜索引擎)