[9]elasticsearch源码深入分析——Plugin组件加载

本篇为elasticsearch源码分析系列文章的第九篇,又到了我们深扒ElasticSearch源码的时候了:)

本篇开始将会详细解释Node实例化的过程中PluginsService的相关内容,PluginService算是Node实例化的重要内容,了解PluginService的加载过程有助于我们理解Node实例化和ElasticSearch启动时工作流程,此外PluginsService还涉及到ElasticSearch中线程池的使用,关于ElasticSearch中线程池的封装使用,我们会在下一篇叙述。

插件的安装

ElasticSearch中的插件是一个允许插入自定义功能的扩展。插件大致分为三类:

  • java插件:这些插件只包含Jar文件,并且必须安装在集群中的每个节点上。安装后,每个节点必须重新启动,该插件才变得可见。比如分词器插件。
  • 站点插件:这些插件包含了静态的Web内容,如JavaScript,HTML和CSS文件,可直接从Elasticsearch访问。站点插件可能只需要在一个节点上安装,并且不需要重新启动就能变得可见。站点插件的内容是通过一个类似的网址访问:HTTP://IP:9200/_plugin/[插件名称]
  • 混合插件:混合插件同时包含jar文件和静态的Web内容

在ElasticSearch的bin目录下,可以执行命令

bin/plugin list:查看已经安装了的ElasticSearch插件。
bin/plugin install [plugin_name]:安装一个ElasticSearch插件。

插件的安装过程如图所示:

插件安装

在安装好之后,在ElasticSearch的plugins目录下就能看到插件包了:

安装好的icu插件

可以看出icu分词插件是个纯java插件。icu
是Elasticsearch的分析器插件,使用国际化组件Unicode(ICU)提供丰富的处理 Unicode编码的工具。该查件对处理亚洲语言特别有用,还有大量对除英语外其他语言进行正确匹配和排序所必须的分词过滤器。

插件何时进行加载

落地到编码层次的话,plugins文件夹中的插件在Node实例化的时候被加载,构建代码如下:

this.pluginsService = new PluginsService(tmpSettings, environment.configFile(), environment.modulesFile(), environment.pluginsFile(), classpathPlugins);

其中environment.pluginsFile()的路径的内容就是xxx\elasticsearch\elasticsearch-6.0.0-rc2\plugins\analysis-icu

ElasticSearch插件扩展机制

在ElasticSearch的org.elasticsearch.plugins的包中提供了若干种插件的扩展类,完全覆盖了所有插件的扩展需求。除了能实现以下接口:

  • ActionPlugin
  • AnalysisPlugin
  • ClusterPlugin
  • DiscoveryPlugin
  • IngestPlugin
  • MapperPlugin
  • NetworkPlugin
  • RepositoryPlugin
  • ScriptPlugin
  • SearchPlugin

进一步定制ElasticSearch外,除了这个类扩展点还声明一些@DeprecatedonModule方法。使用这些方法应该特别注意,使用5.x以前风格扩展语法不能成功构建。这也是成功的开源软件在考虑平滑升级时的设计思路时值得学习的地方。定义了插件的实现方法,这些插件从低版本升级到5.x之后的版本就不会太过艰难。

比如上面提到的icu分词插件,就实现了AnalysisPlugin, MapperPlugin,这两个接口。

public class AnalysisICUPlugin extends Plugin implements AnalysisPlugin, MapperPlugin

关于这些插件的详细解析,我们会在以后的文章中讲解。

PluginsService类的构造函数解析

一般查看组件源码都是先从构造函数开始,PluginsService的构造函数为PluginsService(Settings settings, Path configPath, Path modulesDirectory, Path pluginsDirectory, Collection<Class<? extends Plugin>> classpathPlugins)

有如下五个参数,大都是路径设定类的:

  • settings:ElasticSearch启动时的系统设定
  • Path:ElasticSearch的config配置文件的目录,类型为Path
  • modulesDirectory:ElasticSearch的modules目录,类型为Path
  • pluginsDirectory:ElasticSearch的plugins目录,类型为Path
  • classpathPlugins:在classpath路径中的插件,是Plugin类的子类集合,有这种情况的出现主要是为了在测试和使用transport clients的情况下加载插件。
加载classpathPlugins中的插件

PluginsService先构造了一个List,List的元素为PluginsInfo类型和Plugin类型的元组(Tuple)。

接着再遍历classpathPlugins的值中的Plugin实现类对象,通过反射Plugin的实现类,调用方法getConstructors()得到Plugin的子类的构造函数,得到构造函数后,对构造函数进行一系列的检查:

  • 自定义实现的Plugin子类必须有public的构造函数
  • 有且只能有一个构造函数
  • 接受参数不能大于两个,且第一个为Settings类型,第二个为Path类型。看过我以前文章的同学对Setting肯定不会陌生。

由此可以知道,想自己实现ElasticSearch的插件,就必须继承Plugin类,定义一个构造函数,根据要实现插件的类型实现不同的接口,比如SearchPlugin,ScriptPlugin,RepositoryPlugin

构造Plugins之modulesDirectory

接下来遍历modules路径中各个module的plugin-descriptor.properties文件,取出文件中的如下属性:

  • name
  • description
  • version
  • elasticsearch.version
  • java.version
  • has.native.controller:该插件是否需要本地控制器
  • requires.keystore:该插件是否需要ElasticSearch创建秘钥库

构造出各个modulePluginInfo对象,然后遍历出各个module下面的jar包的路径,这样每个module的jar包和信息就都有了,我们可以看到ElasticSearch是封装了一个内部类Bundle,如下图:

内部封装类Bundle

至此找到了所有需要加载的module,下面是加载所有的plugins

构造Plugins之pluginsDirectory

首先调用checkForFailedPluginRemovals()方法,遍历pluginsDirectory路径中所有的包含.removing-字符的文件,抛出应该remove该插件的异常IllegalStateException。

检查完成后,遍历pluginsDirectory路径下的文件,遍历过程中,很细心的检查了当前查询路径是否是MacOS或者可能的桌面系统,而不是服务器。如果符合上述条件就跳过该次遍历,不符合的话依然按照加载module的方法那样,取得plugins文件夹下的各个plugin的plugin-descriptor.properties文件,依次加载name,description,version,elasticsearch.version,java.version,has.native.controller,requires.keystore属性,封装成PluginInfo,查找出jar包,最后封装成Bundle对象。

这样就得到了两个Bundle对象,一个modules,一个plugins。构造一个整体集合后,检查其中的jar包,避免jar-hell

至此PluginsService对象就已经构造完毕,通过赋值语句this.pluginsService = new PluginsService(tmpSettings, environment.configFile(), environment.modulesFile(), environment.pluginsFile(), classpathPlugins),Node就对象获得了PluginsService的对象。

PluginsService构造函数总结

我们整理一下PluginsService的构造函数做了哪些工作,

  • this.configPath = configPath:设置了configPath的路径值
  • this.info = new PluginsAndModules(pluginsList, modulesList):加载了Plugins和Modules中的基本信息和jar路径
  • his.plugins = Collections.unmodifiableList(pluginsLoaded):加载了bundle对象,bundle中包含了基础信息和所有jar的URL

PluginsService类的作用

在通篇过完了PluginsService类的构造参数后,我们继续来看PluginsService对象在Node中起到的作用。

在Node对象构建完了PluginsService对象后,紧接着在Node中,通过PluginsService对象的updatedSettings()方法,将PluginsService类在构造时从modulesplugins路径中加载的plugin对象取出遍历,依次调用各个plugin的additionalSettings()方法。然后put更新Settings对象,达到了更新Settings对象的目的。

additionalSettings()这个方法在不同的plugin实现类中有不同实现,具体作用是构建插件运行过程中需要的Settings对象。如下图是Netty4plugin的实现:

Netty4Plugin的实现

由此可见,PluginsService组件中保存的Plugin元组是ElasticSearch发挥功能的重要内容,其中加载的Modules路径下的Plugin组件一起构成了ElasticSearch的核心主干功能。

ElasticSearch中线程池的加载参数直接来源于PluginsService,下一篇文章我们会讲解在Node实例化过程中线程池的封装过程,希望大家持续关注哦^ _ ^。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容