插件的作用和分类
elasticsearch
(简称 es)是一款使用宽泛的反对实时搜寻的数据库。罕用于全文检索、时序数据分析等畛域。es 自身基于模块设计,同时反对插件定制,当现有的性能和插件无奈满足需要的时候,咱们能够基于 es 的插件框架和接口,实现本人的插件,实现性能。
常见的插件,有中文分词、hdfs 数据备份还原、云平台主动发现 (ec2, gce, azure) 等。es 的免费模块 xpack
也是基于插件机制开发进去的,xpack 提供了诸如 index 申明周期治理、es 监控、平安认证、告警、机器学习、sql 等实用功能。
应用插件实现这些性能的益处是,可能更好的整合 es 的基础设施,不便部署。
es 的插件次要分为如下几大类:
- 分词插件
- 扩大 restful 接口
- 集群和主动发现
- Ingest 插件
- 存储插件
- 脚本扩大
- 搜寻相干
- 个别插件
这个系列将会基于笔者的理论开发教训,介绍其中 扩大 restful 接口
, Ingest 插件
和个别插件
。
es 提供的基础设施
在开始开发前,咱们能够先理解一下,作为 es 的插件能够从 es 的中获取哪些可间接应用的根底接口。
- Client: 相当于 restful Client,但其外部实现并不是简略的 http 申请
- ClusterService: 集群相干治理接口
- ScriptService: script 相干
- ThreadPool: es 治理的线程池,实现多线程或定时工作
- NodeEnvironment: 节点环境
- …
实时上基础设施还有许多,笔者也不是全副理解。只是列举一下用到过的。es 官网对插件开发的文档反对还是很无限的,所以如果心愿进行插件开发的话,学习已有的插件源码,甚至是跟踪到 es 外围源码简直是必须的。
插件部署
插件在 es 中运行,除了须要实现一些接口,还须要遵循一些约定。这些约定关系到开发和部署。
在 es 中内部插件被部署在 plugins
目录下。有两种形式能够部署插件,一种是通过 es 自带的 elasticsearch-plugin
命令装置打包好的插件 zip 包;另一种是间接复制插件到 plugins 目录下。个别在开发测试阶段应用第二种形式比拟不便。如果心愿他人应用,则最好依照要求公布成 zip 包。
但无论是哪种形式,一个插件最终能被 es 加载必须满足几个条件:
- 在
plugins
目录下有对应插件的目录 - 目录中蕴含打好的 jar 包和依赖包
- 目录中蕴含
plugin-descriptor.properties
插件形容文件 - 目录中蕴含
plugin-security.policy
文件,申明插件会用到的 java 平安项
以 repository-hdfs
插件为例,插件中的蕴含文件如下(省略了依赖的 jar 包):
repository-hdfs
├── plugin-descriptor.properties
├── plugin-security.policy
├── repository-hdfs-7.0.0.jar
...
plugin-descriptor.properties
例如
description=The HDFS repository plugin adds support for Hadoop Distributed File-System (HDFS) repositories.
version=7.0.0
name=repository-hdfs
classname=org.elasticsearch.repositories.hdfs.HdfsPlugin
java.version=1.8
elasticsearch.version=7.0.0
extended.plugins=
has.native.controller=false
plugin-descriptor.properties
中最要害的局部是 elasticsearch.version
和classname
。前者申明了插件兼容的 es 版本(这个版本必须与正在运行的 es 版本 exactly 统一),后者是插件的入口类
plugin-security.policy
例如
grant {
permission java.lang.RuntimePermission "getClassLoader";
permission java.lang.RuntimePermission "accessDeclaredMembers";
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
permission java.lang.RuntimePermission "setContextClassLoader";
permission java.util.PropertyPermission "*", "read,write";
permission java.lang.RuntimePermission "shutdownHooks";
permission javax.security.auth.AuthPermission "getSubject";
permission javax.security.auth.AuthPermission "doAs";
permission javax.security.auth.PrivateCredentialPermission "org.apache.hadoop.security.Credentials * \"*\"","read";
permission java.lang.RuntimePermission "accessClassInPackage.sun.security.krb5";
permission javax.security.auth.AuthPermission "modifyPrivateCredentials";
permission javax.security.auth.AuthPermission "modifyPrincipals";
permission javax.security.auth.PrivateCredentialPermission "javax.security.auth.kerberos.KeyTab * \"*\"","read";
permission javax.security.auth.PrivateCredentialPermission "javax.security.auth.kerberos.KerberosTicket * \"*\"","read";
permission java.lang.RuntimePermission "loadLibrary.jaas";
permission java.lang.RuntimePermission "loadLibrary.jaas_unix";
permission java.lang.RuntimePermission "loadLibrary.jaas_nt";
permission javax.security.auth.AuthPermission "modifyPublicCredentials";
permission java.security.SecurityPermission "putProviderProperty.SaslPlainServer";
permission java.security.SecurityPermission "insertProvider.SaslPlainServer";
permission javax.security.auth.kerberos.ServicePermission "*", "initiate";
permission java.net.SocketPermission "*", "connect";
permission java.net.SocketPermission "localhost:0", "listen,resolve";
};
plugin-security.policy
是插件对敏感资源 (比方本地文件) 或者利用代码 (类的办法) 的拜访申明。因为 es 是在 java.security
开启的状况下运行插件的,所以有很多咱们悉数平时的操作都无奈通过 jvm 的 Access Control 机制的查看(例如读写文件、反射、Classloader 操作、Socket 相干),会报莫名其妙的权限问题。es 要求插件开发者在 plugin-security.policy
中申明对敏感资源的需要,并在代码中应用 AccessController.doPrivileged
包裹蕴含敏感操作的代码。
插件开发的难点
笔者总结了在插件开发过程中遇到的难点:
- jar hell。es 对有抵触版本的 jar 包采取了 绝不姑息 的态度。无论是 es 本身依赖的 lib,还是插件的 lib,插件之间的 lib,凡是在加载过程过发现有 jar 包抵触,就会报
jar hell
的谬误。这给插件治理依赖带来了很大的艰难。即便你将 es 本身的依赖排除在外,也无奈保证系统装置的其余插件的依赖 jar 包与你插件的依赖 jar 包没有抵触。 - 调试艰难。尽管 es 提供了专门用于单元测试的测试框架,但这块简直没有什么文档,只能本人通过查看官网的插件实现来缓缓摸索。对于具体开发也没有明确的领导,根本只能靠摸索。
- 版本强统一。下面也提到了,
plugin-descriptor.properties
的中的elasticsearch.version
必须与运行的 es 版本完全一致。这给插件的版本散发带来了艰难。 - security.policy 问题。
security.policy
其实很多开发者不相熟的,往往会呈现插件跑起来各种报权限不够。所以须要在调试阶段一一去尝试,尤其是你如果依赖其余 jar,你可能无法控制这些 jar 的外部行为,从而无奈用AccessController.doPrivileged
包裹其外部线程须要拜访敏感资源的代码。有的时候,你发现你曾经申明了plugin-security.policy
,也用AccessController.doPrivileged
做了你感觉正确的解决,还是呈现权限不够,那么就要思考是不是你依赖的 jar 包的外部线程有拜访敏感资源。