包管理器内部原理
包管理器 (CLI) 内部使用各种 Solr API 来安装、部署和更新包。本文档概述了这些 API。
主要特性
-
零中断部署(热部署):应该可以在不重启节点或重新加载核心的情况下安装和更新包,因此部署应该快速,并且不会出现请求失败或陈旧缓存的情况。
-
易于打包
-
标准插件概念,例如,查询解析器、搜索组件、请求处理程序、URP 等,应该在没有任何特殊代码/打包更改的情况下得到支持。
-
用户已经部署(并在生产环境中使用)的工件(包含自定义插件的 jar 文件)应该兼容,无需重新编译或重新打包,以便更广泛地采用。
-
应该支持单 jar 包以及多 jar 包。
-
使用熟悉/标准命名
-
使用业界标准的包管理器概念和术语,类似于 apt、dnf、homebrew 等。
-
类加载器
在系统的核心,我们有类加载器隔离。为了实现这一点,系统被简化为两个分层的类加载器
-
根类加载器,它拥有来自 Solr 类路径的所有 jar 文件。这需要重启 Solr 节点才能更改任何内容。
-
一组命名的类加载器,它们继承自根类加载器。命名的类加载器的生命周期与 ZooKeeper 中的包配置相关联。一旦配置被修改,相应的类加载器就会被重新加载,并且组件会被要求重新加载。
包加载安全性
默认情况下禁用包。使用系统属性 -Denable.packages=true
启动所有节点以使用此功能。
示例
bin/solr start -c -Denable.packages=true
包存储
包存储是一个分布式文件存储,可以在文件系统中存储任意文件。
-
这是一个完全复制的基于文件系统的存储库。
-
它位于每个 Solr 节点上的 <solr.home>/filestore 中。
-
每个条目都是一个文件 + 元数据。元数据命名为
.<filename>.json
。 -
元数据文件包含文件的 sha256 和签名。
-
用户无法创建以句点 (.) 开头的文件。
-
它与文件的内容类型无关。您可以存储 jar 文件以及其他文件。
包存储 API
端点是
-
每个节点中的
PUT /api/cluster/files/{full/path/to/file}
-
GET /api/node/files/{full/path/to/file}
下载文件 -
GET /api/node/files/{full/path/to/file}?meta=true
获取文件的元数据 -
GET /api/node/files/{full/path/to/}
获取/full/path/to
中的文件列表
签署您的工件
使用以下步骤上传使用您的公钥签名的 jar 文件
-
如果您没有带有插件的 jar 文件,请从 GitHub 下载一个示例
curl -o runtimelibs.jar -LO https://github.com/apache/solr/blob/releases/solr/9.7.0/solr/core/src/test-files/runtimecode/runtimelibs.jar.bin?raw=true
-
使用您的私钥对 jar 文件进行签名
openssl dgst -sha1 -sign my_key.pem runtimelibs.jar | openssl enc -base64 | sed 's/+/%2B/g' | tr -d \\n | sed
-
上传带有签名的 jar 文件,将
sig
参数替换为先前命令的输出curl --data-binary @runtimelibs.jar -X PUT https://127.0.0.1:8983/api/cluster/files/mypkg/1.0/myplugins.jar?sig=<signature-of-jar>
-
验证您的 jar 文件上传
curl https://127.0.0.1:8983/api/node/files/mypkg/1.0?omitHeader=true
{ "files":{"/mypkg/1.0":[{ "name":"myplugins.jar", "timestamp":"2019-11-11T07:36:17.354Z", "sha512":"d01b51de67ae1680a84a813983b1de3b592fc32f1a22b662fc9057da5953abd1b72476388ba342cad21671cd0b805503c78ab9075ff2f3951fdf75fa16981420", "sig":["elNjhmWIOgTgbAzeZ+OcwR42N7vqL6Ig9eAqn4YoP2thT7FJuhiaZuCPivjMkD682EBo9gveSCTyXIsZKjOCbQ=="]}]}}
包
一个包具有以下属性
-
一个唯一的名称
-
一个或多个具有以下属性的版本
-
version
:版本字符串 -
files
:来自软件包存储的文件数组
-
对于软件包定义中的每个软件包/版本,都有一个唯一的 SolrResourceLoader
实例。它是 CoreContainer
资源加载器的子级。
Solr 不要求版本字符串遵循任何特定格式 - 它可以是任意字符串,甚至可以是空字符串。 |
packages.json
软件包配置位于 ZooKeeper 中名为 packages.json
的文件中。在任何给定时刻,我们可以在软件包配置中拥有给定软件包的多个版本。系统将始终使用最新版本。版本按其值以字典顺序排序,最大的字符串被认为是最新版本。
版本字符串的字典顺序意味着,对于具有版本 1.2.0、1.9.0、1.11.0 的软件包,Solr 会选择 1.9.0 作为最新版本。 |
例如
{
"packages" : {
"mypkg" : {
"name": "mypkg",
"versions": [
{"version" : "0.1",
"files" : ["/path/to/myplugin/1.1/plugin.jar"]
},
{"version" : "0.2",
"files" : ["/path/to/myplugin/1.0/plugin.jar"]
}]}}}
API 端点
-
GET /api/cluster/package
获取软件包列表 -
POST /api/cluster/package
编辑软件包-
add
命令:添加软件包的版本 -
delete
命令:删除软件包的版本
-
并行使用多个版本
我们在集合配置中使用 params.json
来存储它使用的软件包版本。默认情况下,它是 $LATEST
。
{"params":{
"PKG_VERSIONS": {
"mypkg": "0.1", (1)
"pkg2" : "$LATEST", (2)
}}}
1 | 对于 mypkg ,使用版本 0.1 ,无论是否有更新的版本可用。 |
2 | 对于 pkg2 ,使用最新版本。这是可选的。默认值为 $LATEST 。 |
因此,在上面的示例中,如果 |
在插件中使用软件包
任何类名都可以用软件包名称作为前缀,例如 mypkg:fully.qualified.ClassName
,Solr 将使用软件包的最新版本加载类。从软件包加载的插件不能依赖于核心级别的类。
solrconfig.xml
中的插件声明<requestHandler name="/myhandler" class="mypkg:full.path.to.MyClass">
</requestHandler>
完整的工作示例
-
创建软件包
curl https://127.0.0.1:8983/api/cluster/package -H 'Content-type:application/json' -d ' {"add": { "package" : "mypkg", "version":"1.0", "files" :["/mypkg/1.0/myplugins.jar"]}}'
-
验证创建的软件包
curl https://127.0.0.1:8983/api/cluster/package?omitHeader=true
{"result":{ "znodeVersion":0, "packages":{"mypkg":[{ "version":"1.0", "files":["/mypkg/1.0/myplugins.jar"]}]}}}
-
此时,该软件包应该可以使用了。接下来,从软件包中在集合中注册一个插件。请注意应用于
class
属性的mypkg:
前缀。也可以通过编辑solrconfig.xml
来实现相同的结果curl https://127.0.0.1:8983/solr/gettingstarted/config -H 'Content-type:application/json' -d '{ "create-requesthandler": { "name": "/test", "class": "mypkg:org.apache.solr.core.RuntimeLibReqHandler" }}'
-
验证是否创建了组件,并且它正在使用软件包的正确版本来加载类
curl https://127.0.0.1:8983/solr/gettingstarted/config/requestHandler?componentName=/test&meta=true&omitHeader=true
{ "config":{"requestHandler":{"/test":{ "name":"/test", "class":"mypkg:org.apache.solr.core.RuntimeLibReqHandler", "_packageinfo_":{ "package":"mypkg", "version":"1.0", "files":["/mypkg/1.0/myplugins.jar"]}}}}}
-
测试请求处理程序
curl https://127.0.0.1:8983/solr/gettingstarted/test?omitHeader=true
{ "params":{ "omitHeader":"true"}, "context":{ "webapp":"/solr", "path":"/test", "httpMethod":"GET"}, "class":"org.apache.solr.core.RuntimeLibReqHandler", "loader":"java.net.FactoryURLClassLoader"}
-
更新组件的版本。获取新版本的 jar 包,签名并上传
curl -o runtimelibs3.jar -LO https://github.com/apache/solr/blob/releases/solr/9.7.0/solr/core/src/test-files/runtimecode/runtimelibs_v3.jar.bin?raw=true openssl dgst -sha1 -sign my_key.pem runtimelibs.jar | openssl enc -base64 | sed 's/+/%2B/g' | tr -d \\n | sed curl --data-binary @runtimelibs3.jar -X PUT https://127.0.0.1:8983/api/cluster/files/mypkg/2.0/myplugins.jar?sig=
-
验证它
curl https://127.0.0.1:8983/api/node/files/mypkg/2.0?omitHeader=true
{ "files":{"/mypkg/2.0":[{ "name":"myplugins.jar", "timestamp":"2019-11-11T11:46:14.771Z", "sha512":"60ec88c2a2e9b409f7afc309273383810a0d07a078b482434eda9674f7e25b8adafa8a67c9913c996cbfb78a7f6ad2b9db26dbd4fe0ca4068f248d5db563f922", "sig":["ICkC+nGE+AqiANM0ajhVPNCQsbPbHLSWlIe5ETV5835e5HqndWrFHiV2R6nLVjDCxov/wLPo1uK0VzvAPIioUQ=="]}]}}
-
添加软件包的新版本
curl https://127.0.0.1:8983/api/cluster/package -H 'Content-type:application/json' -d ' {"add": { "package" : "mypkg", "version":"2.0", "files" :["/mypkg/2.0/myplugins.jar"]}}'
-
验证插件以查看是否正在使用软件包的正确版本
curl https://127.0.0.1:8983/solr/gettingstarted/config/requestHandler?componentName=/test&meta=true&omitHeader=true
{ "config": { "requestHandler": { "/test": { "name": "/test", "class": "mypkg:org.apache.solr.core.RuntimeLibReqHandler", "_packageinfo_": { "package": "mypkg", "version": "2.0", "files": [ "/mypkg/2.0/myplugins.jar" ] }}}}}
-
测试插件
curl https://127.0.0.1:8983/solr/gettingstarted/test?omitHeader=true
{ "params": { "omitHeader": "true" }, "context": { "webapp": "/solr", "path": "/test", "httpMethod": "GET" }, "class": "org.apache.solr.core.RuntimeLibReqHandler", "loader": "java.net.FactoryURLClassLoader", "Version": "2" }
请注意,
Version
值为"2"
,这意味着插件已更新。