最近需要研究搜索的集羣。由於大腦日漸萎縮,只好把代碼記下來以供參考,好久沒在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中。
第一次寫關於開源項目研究的筆記,不盡之處希望大家多多指正。
有想一起研討的也多多給我留言。