参考资料:
http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-plugins.html
http://blog.trifork.com/2013/01/10/how-to-write-an-elasticsearch-river-plugin/
plugin命令使用
elasticsearch能够使用bin/plugin方便的添加插件,命令格式:plugin install url
#elasticsearch会自动从github.com/mobz/elasticsearch-head/archive/master.zip下载插件
sh bin/plugin install mobz/elasticsearch-head
#也可以直接指定url
sh bin/plugin install
#安装本地插件
sh bin/plugin install yourplugin_name _Absolute_Path
除此以外,一般情况下可以把插件直接复制到plugins/[yourname]/目录下,即可完成安装。
自定义插件开发
自定义插件开发需要完成几个步骤:
配置es-plugin.properties
继承自AbstractPlugin的实现类,用于注册plugin。
Module的实现类,提供了plugin接口绑定等信息。
River实现类,river-plugin的真正实现。
es-plugin.properties
es不能通过自动扫描发现要加载的plugin实现类,因此需要在classpath下放置es-plugin.properties文件用以说明需要加载的plugin。主要代码就一行:
plugin=com.xxx.xxx.YourPLugin
我的配置如下,其中多增加的两行主要是为了在初始化时获取更多地信息(不是必要内容)。
plugin=com.pangyangyang.elasticsearch.plugin.river.MessageRiverPlugin
version=${project.version}
description=${project.description}
AbstractPlugin实现
plugin类用于注册插件和提供插件的基本信息,首先通过name和description方法提供了插件的基本说明,这部分信息即es-plugin.properties中扩展的内容。
@Override
public String name() {
return "message-" + Build.getInstance().getVersion();
}
@Override
public String description() {
return Build.getInstance().getDescription();
}
然后实现onModule方法,用于注入Module。如此我的plugin便以message作为type注册到ES了。
public void onModule(RiversModule module) {
module.registerRiver("message", MessageRiverModule.class);
}
要说明的是onModule的参数不一定是RiversModule,需要根据你的plugin类型来,它可以是AnalysisModule、ScriptModule、RestModule等等。
Module实现
Module提供了插件的配置信息,典型的接口绑定——这个信息用于为River创建注入器(在River中@Inject中使用)。
public class MessageRiverModule implements Module {
@Override
public void configure(Binder binder) {
binder.bind(River.class).to(MessageRiver.class).asEagerSingleton();
}
}
这里把MessageRiver类绑定到了River接口类型,并且声明为立即初始化的,也就是在Guice初始化的时候就会创建MessageRiver实例而不是等到需要的时候才创建。
River实现
public class MessageRiver extends AbstractRiverComponent implements River {
private Client client;
@Inject
protected MessageRiver(RiverName riverName, RiverSettings settings, Client client) {
super(riverName, settings);
this.client = client;
}
@Override
public void start() {
//your plugin action ...
}
@Override
public void close() {
//close plugin
}
}
Plugin的实现了River,继承自AbstractRiverComponent。
使用注解@Inject标识构造函数,ES会自动注入你需要的参数,这里包括riverName、settings和当前Node的客户端。
到此为止你可以使用下面的代码向ES添加river的实例了。这里_river是一个特殊的index,message是一个Type,Id为_meta的document就是一个Indexed Document,它指明了plugin的类型是message,其余的参数会作为RiverSettings settings用于初始化。
curl -XPUT localhost:9200/_river/message/_meta -d '{
"type":"message",
"name":"new message"
}'
同样地可以通过创建多个不同个Type启动多个message river实例,而每个实例都会通过构造方法创建(settings因此可以不同)。
start方法是plugin逻辑的主要实现,会在两种情况下执行:
在_river Index中创建了新的river实例。
ES每次启动时会调用已经注册的river实例的start方法。
close方法即plugin的销毁方法,会在两种情况下执行:
在_river中删除了plugin。
_river实例所在的node shutdown或者_river被重新分配给新的node时。