elasticsearch通过guice注入Node组装启动过程

网友投稿 276 2022-08-03


elasticsearch通过guice注入Node组装启动过程

目录elasticsearch启动过程首先看一下node的初始化启动各个模块的过程插件的加载过程

elasticsearch启动过程

elasticsearch的启动过程是根据配置和环境组装需要的模块并启动的过程。这一过程就是通过guice注入各个功能模块并启动这些模块,从而得到一个功能完整的node。正如之前所说elasticsearch的模块化特点,它的各个功能都是独立实现,然后实现通过guice对外提供。

首先看一下node的初始化

node接口的唯一实现是InternalNode,它的初始化代码如下所示:

public InternalNode(Settings preparedSettings, boolean loadConfigSettings) throws ElasticsearchException {

final Settings pSettings = settingsBuilder().put(preparedSettings)

.put(Client.CLIENT_TYPE_SETTING, CLIENT_TYPE).build();

Tuple tuple = Ihttp://nternalSettingsPreparer.prepareSettings(pSettings, loadConfigSettings);

tuple = new Tuple<>(TribeService.processSettings(tuple.v1()), tuple.v2());

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

//启动插件service,加载并启动插件

this.pluginsService = new PluginsService(tuple.v1(), tuple.v2());

this.settings = pluginsService.updatedSettings();

// create the environment based on the finalized (processed) view of the settings

this.environment = new Environment(this.settings());

CompressorFactory.configure(settings);

//配置node环境

final NodeEnvironment nodeEnvironment;

try {

nodeEnvironment = new NodeEnvironment(this.settings, this.environment);

} catch (IOException ex) {

throw new ElasticsearchIllegalStateException("Failed to created node environment", ex);

}

boolean success = false;

try {

//加载各个模块

ModulesBuilder modules = new ModulesBuilder();

modules.add(new Version.Module(version));

modules.add(new CacheRecyclerModule(settings));

modules.add(new PageCacheRecyclerModule(settings));

modules.add(new CircuitBreakerModule(settings));

modules.add(new BigArraysModule(settings));

modules.add(new PluginsModule(settings, pluginsService));

modules.add(new SettingsModule(settings));

modules.add(new NodeModule(this));

modules.add(new NetworkModule());

modules.add(new ScriptModule(settings));

modules.add(new EnvironmentModule(environment));

……

}

可以看到node的初始化过程主要包括三部分

第一是启动插件服务(es提供了插件功能来进行扩展功能,这也是它的一个亮点),加载需要的插件

第二是配置node环境

最后就是通过guice加载各个模块。

启动各个模块的过程

插件服务稍微复杂最后再说。elasticsearch各个功能模块实现的非常好,解耦非常完美,很多模块都实现了生命周期接口,只有启动它才能够对外提供服务,它的启动过程也是功能模块初始化的过程。因此,node节点的启动过程也就是这些模块初始化的过程。如下面的代码片段所示:

public Node start() {

if (!lifecycle.moveToStarted()) {

return this;

}// hack around dependency injection problem (for now...)

injector.getInstance(Discovery.class).setAllocationService(injector.getInstance(AllocationService.class));

for (Class extends LifecycleComponent> plugin : pluginsService.services()) {

injector.getInstance(plugin).start();

}

    //通过guice获取各个模块的service接口并启动

injector.getInstance(MappingUpdatedAction.class).start();

injector.getInstance(IndicesService.class).start();

injector.getInstance(IndexingMemoryController.class).start();

injector.getInstance(IndicesClusterStateService.class).start();

injector.getInstance(IndicesTTLService.class).start();

injector.getInstance(RiversManager.class).start();

injector.getInstance(SnapshotsService.class).start();

injector.getInstance(TransportService.class).start();

……

}

每个模块service都会实现一个start接口,模块功能初始化过程都是这这个函数中实现。每个模块的具体启动过程后面会有涉及,这里就不做深入分析。

插件的加载过程

每个node在加载各个模块前,会首先加载所需要的插件,如果有些插件加载不成功node会启动失败。这里会加载三类插件:首先是配置插件,配置到节点配置文件中插件,如分词插件等;然后查找classpathhttp://中能找到的插件,这些插件一般防止在plugin文件夹中;最后是加载site插件,site插件是不涉及java代码的纯网站式插件,如监控插件head,bigdesk等。任何使用者都可以开发自己需要的插件,只要按着elasticsearch相关版本的插件开发规范来实现即可。

public PluginsService(Settings settings, Environment environment) {

super(settings);

this.environment = environment;

……

ImmutableList.Builder> tupleBuilder = ImmutableList.builder();

// 加载配置插件

String[] defaultPluginsClasses = settings.getAsArray("plugin.types");

for (String pluginClass : defaultPluginsClasses) {

Plugin plugin = loadPlugin(pluginClass, settings);

PluginInfo pluginInfo = new PluginInfo(plugin.name(), plugin.description(), hasSite(plugin.name()), true, PluginInfo.VERSION_NOT_AVAILABLE);

if (logger.isTraceEnabled()) {

logger.trace("plugin loaded from settings [{}]", pluginInfo);

}

tupleBuilder.add(new Tuple<>(pluginInfo, plugin));

}

// 查找classpatch中的所有插件

loadPluginsIntoClassLoader();

if (loadClasspathPlugins) {

tupleBuilder.addAll(loadPluginsFromClasspath(settings));

}

this.plugins = tupleBuilder.build();

// We need to build a List of jvm and site plugins for checking mandatory plugins

Map jvmPlugins = Maps.newHashMap();

List sitePlugins = Lists.newArrayList();

for (Tuple tuple : this.plugins) {

jvmPlugins.put(tuple.v2().name(), tuple.v2());

if (tuple.v1().isSite()) {

sitePlugins.add(tuple.v1().getName());

}

}

// 加载site插件

ImmutableList> tuples = loadSitePlugins();

for (Tuple tuple : tuples) {

sitePlugins.add(tuple.v1().getName());

}

// 检验代理插件,如果有加载不成功的插件就抛出异常,停止node启动。

String[] mandatoryPlugins = settings.getAsArray("plugin.mandatory", null);

if (mandatoryPlugins != null) {

Set missingPlugins = Sets.newHashSet();

for (String mandatoryPlugin : mandatoryPlugins) {

if (!jvmPlugins.containsKey(mandatoryPlugin) && !sitePlugins.contains(mandatoryPlugin) && !missingPlugins.contains(mandatoryPlugin)) {

missingPlugins.add(mandatoryPlugin);

}

}

if (!missingPlugins.isEmpty()) {

throw new ElasticsearchException("Missing mandatory plugins [" + Strings.collectionToDelimitedString(missingPlugins, ", ") + "]");

}

}

……

}

以上就是pluginservice的初始化过程,在它的初始化过程中,加载所有能够找的插件。插件的启动在其他功能模块之前,些插件,如分词插件,启动不成功则会对节点的功能造成影响,因此会在这里就中断节点的启动过程让用户知道。这就是节点的启动过程。插件加载成功,各个功能模块加载并启动成功,节点就启动成功。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:elasticsearch集群cluster主要功能详细分析(elasticsearch集群原理)
下一篇:elasticsearch分布式及数据的功能源码分析(elasticsearch分布式原理)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~