Solr配置:包管理器内核机制与API详解
包管理器(CLI)内部使用各种Solr API来安装、部署和更新包。本文档提供了这些API的概述和详细使用指南。
核心特性
零中断部署(热部署)
- 支持在不重启节点或重新加载核心的情况下安装和更新包
- 部署快速,无请求失败或缓存过期
- 实现真正的热部署能力
简化打包流程
标准插件概念支持
- 查询解析器、搜索组件、请求处理器、URP等标准插件概念
- 无需特殊代码/打包更改即可支持
- 保持传统插件开发模式
向后兼容性
- 用户已部署的构件(包含自定义插件的jar)兼容
- 无需重新编译或重新打包
- 促进更广泛的采用
灵活的包格式
- 支持单jar包和多jar包
- 使用熟悉/标准的命名约定
- 采用行业标准的包管理器概念和术语(类似apt、dnf、homebrew等)
类加载器架构
类加载器隔离是系统的核心。系统简化为两层类加载器:
根类加载器
- 包含Solr类路径中的所有jar
- 需要Solr节点重启才能更改
命名类加载器集合
- 从根类加载器继承
- 生命周期与ZooKeeper中的包配置绑定
- 配置修改后,相应的类加载器重新加载,组件被要求重新加载
包加载安全机制
默认安全策略
包功能默认禁用。需要使用系统属性-Denable.packages=true
启动所有节点来使用此功能。
1 | bin/solr start -c -Denable.packages=true |
密钥管理
上传公钥
包二进制文件必须使用私钥签名,确保公钥发布在包存储的信任存储中。
1 | # 生成私钥 |
包存储系统
系统概述
包存储是一个分布式文件存储,可以在文件系统中存储任意文件。
核心特性
- 完全复制的基于文件系统的存储库
- 位置:每个Solr节点的
<solr.home>/filestore
- 每个条目包含文件 + 元数据
- 元数据文件命名为
.<filename>.json
- 元数据文件包含sha256和文件签名
- 用户不能创建以句点(.)开头的文件
- 与文件内容类型无关,可存储jar和其他文件
包存储工作原理
当文件上传到包存储时:
- 保存到本地文件系统
- 与元数据一起保存,元数据文件存储jar文件的sha512和签名
- 要求集群中的每个活动节点也下载该文件
包存储API
核心端点
PUT /api/cluster/filestore/files/{full/path/to/file}
- 上传新文件并添加到文件存储GET /api/cluster/filestore/files/{full/path/to/file}
- 下载文件存储中已有的文件GET /api/cluster/filestore/metadata/{full/path/to/file}
- 获取特定文件的元数据或目录中可用文件列表
构件签名流程
1. 获取示例jar文件
1 | curl -o runtimelibs.jar -LO https://github.com/apache/solr/blob/releases/solr/9.9.0/solr/core/src/test-files/runtimecode/runtimelibs.jar.bin?raw=true |
2. 使用私钥签名jar
1 | openssl dgst -sha1 -sign my_key.pem runtimelibs.jar | openssl enc -base64 | sed 's/+/%2B/g' | tr -d \\n |
3. 上传带签名的jar
1 | curl --data-binary @runtimelibs.jar -X PUT \ |
4. 验证jar上传
1 | curl "http://localhost:8983/api/cluster/filestore/metadata/mypkg/1.0?omitHeader=true" |
响应示例:
1 | { |
包配置系统
包属性结构
一个包具有以下属性:
- 唯一名称
- 一个或多个版本,每个版本具有:
version
:版本字符串files
:来自包存储的文件数组
对于包定义中的每个包/版本,都有一个唯一的SolrResourceLoader
实例,这是CoreContainer
资源加载器的子级。
注意:Solr不要求版本字符串遵循任何特定格式 - 可以是任意字符串甚至空字符串。
packages.json配置
包配置存在于ZooKeeper中名为packages.json
的文件中。任何时刻都可以在包配置中有给定包的多个版本。系统总是使用最新版本。版本按其值的字典序排序,最大的字符串被认为是最新的。
重要警告:版本字符串的字典序意味着对于具有版本1.2.0、1.9.0、1.11.0的包,Solr会选择1.9.0作为最新版本。
配置示例
1 | { |
API端点操作
包管理API
GET /api/cluster/package
- 获取包列表POST /api/cluster/package
- 编辑包add
命令:添加包版本delete
命令:删除包版本
版本管理操作
升级包
使用add
命令添加高于当前版本的版本。
降级包
使用delete
命令删除最高版本,选择次高版本。
并行使用多个版本
使用集合配置中的params.json
存储包使用的版本。默认情况下是$LATEST
。
1 | { |
说明:
mypkg
:无论是否有更新版本,都使用版本0.1
pkg2
:使用最新版本(这是可选的,默认是$LATEST
)
注意:params.json
中的包版本实际上指示Solr选择不大于提供值的最大版本的包。
版本更新工作流
- 添加包的新版本
- 包加载器加载类并通知每个插件持有者新版本的可用性
- 检查是否应该使用特定版本,如果是则忽略更新
- 如果不是,则重新加载插件
在插件中使用包
类名前缀
任何类名都可以用包名作为前缀,例如mypkg:fully.qualified.ClassName
,Solr会使用包的最新版本来加载类。从包加载的插件不能依赖于核心级类。
solrconfig.xml中的插件声明
1 | <requestHandler name="/myhandler" class="mypkg:full.path.to.MyClass"> |
完整工作示例
1. 创建包
1 | curl http://localhost:8983/api/cluster/package \ |
2. 验证创建的包
1 | curl http://localhost:8983/api/cluster/package?omitHeader=true |
响应示例:
1 | { |
3. 注册集合中的插件
1 | curl http://localhost:8983/solr/gettingstarted/config \ |
4. 验证组件创建
1 | curl "http://localhost:8983/solr/gettingstarted/config/requestHandler?componentName=/test&meta=true&omitHeader=true" |
响应示例:
1 | { |
5. 测试请求处理器
1 | curl "http://localhost:8983/solr/gettingstarted/test?omitHeader=true" |
6. 更新组件版本
上传新版本的jar、签名并上传:
1 | curl -o runtimelibs3.jar -LO https://github.com/apache/solr/blob/releases/solr/9.9.0/solr/core/src/test-files/runtimecode/runtimelibs_v3.jar.bin?raw=true |
7. 添加新包版本
1 | curl http://localhost:8983/api/cluster/package \ |
避免自动升级
设置集合级别的属性来固定包版本:
1 | curl http://localhost:8983/solr/gettingstarted/config/params \ |
最佳实践建议
1. 安全考虑
- 始终使用密钥签名验证包的完整性
- 定期更新和轮换签名密钥
- 限制包上传权限
2. 版本管理
- 使用有意义的版本号命名规则
- 注意字典序排序的影响
- 建立版本回滚机制
3. 部署策略
- 在测试环境验证新包
- 使用滚动更新减少服务影响
- 监控部署后的系统状态
4. 性能优化
- 合理控制包的大小和数量
- 避免不必要的包重载
- 监控类加载器的内存使用
包管理器提供了现代化的插件管理能力,通过合理使用其API和最佳实践,可以实现高效、安全的插件生命周期管理。