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<Class<? extends Plugin>> 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。
這裏寫圖片描述

每個discovery module 包含了不同的多個Discovery模塊,每個discovery模塊都是先了自己的publishi方法,通過廣播的形式將master node接受到的node change event時間告訴其他的監聽器。

其中最重要的就是 ZenDiscovery,它負責在局域網內通過多播(multi-broadcast)或者單播的形式發現其他節點並將之納入cluster中。

第一次寫關於開源項目研究的筆記,不盡之處希望大家多多指正。
有想一起研討的也多多給我留言。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章