- 搜索引擎
- 全文检索
- 可观测性
- 数据分析
【免费下载链接】OpenSearch
🔎 Open source distributed and RESTful search engine.
本篇技术指南围绕 OpenSearch 1.2.0 版本发布说明(release-notes/opensearch.release-notes-1.2.0.md)展开,重点剖析该版本两大核心能力:全新引入的分片级索引压力(Shard Level Indexing Pressure)与引擎插件可扩展的 Translog 删除策略/EngineConfig 覆盖机制,并系统梳理 Lucene、gson、Jackson、Netty 等依赖升级以及 Spotless、JaCoCo、Windows/FreeBSD 构建支持等工程质量改进。读完本文,你将掌握 1.2.0 的全部可配置索引压力参数与默认值、拒绝判定流程、插件扩展点的使用方式,以及版本升级时需要关注的兼容性变化。
版本概览:1.2.0 的核心变化
OpenSearch 1.2.0 是 1.x 分支上的一个功能性大版本,从发布说明([Version] Increment 1.x to 1.2 (#1239))可见其版本号自此从 1.1 提升到 1.2。该版本的变化可归为四类:
- 分片级索引压力(Shard Level Indexing Pressure):作为本版本旗舰特性,将原本"节点级"的索引压力内存核算下沉到"分片级",实现更细粒度、更公平的拒绝控制;
- 引擎插件扩展机制:新增
TranslogDeletionPolicy扩展点,并引入EngineConfigFactory机制,允许插件在不整体替换引擎的前提下覆盖引擎配置; - 依赖与底层库升级:Lucene 升级到 8.10.1,同时升级 gson、Jackson、Netty、Mockito、Hadoop(hdfs 插件)等;
- 构建质量与平台支持:全仓库启用 Spotless 格式检查、引入 JaCoCo 覆盖率、修复 Windows/FreeBSD 构建问题,并移除存在 CVE 的旧 ES 库。
分片级索引压力(Shard Level Indexing Pressure)—— 旗舰特性
发布说明中"Add Shard Level Indexing Pressure (#1336) (#1343)"一条给出了该特性的完整定位:
Shard level indexing pressure improves the current Indexing Pressure framework which performs memory accounting at node level and rejects the requests. This takes a step further to have rejections based on the memory accounting at shard level along with other key performance factors like throughput and last successful requests.
即:在既有节点级内存核算与拒绝机制之上,进一步引入分片级内存核算,并叠加**吞吐量(throughput)与最近成功请求(last successful requests)**等性能因子,作为拒绝判定的依据。
从节点级到分片级的演进
在 1.2.0 之前,OpenSearch 的索引压力框架(IndexingPressure)在节点维度进行内存核算:当节点上所有索引请求占用的内存超过节点级阈值时直接拒绝新请求。这种做法的问题在于——某个索引或分片"吃"掉大量内存时,会连累同一节点上其他健康的索引。
分片级索引压力把核算单位细化到 shard。从源码结构看,该特性由server/src/main/java/org/opensearch/index/目录下的系列类协同实现:
- ShardIndexingPressure.java:框架级核心类,继承自节点级
IndexingPressure,向 Transport Action 层提供markCoordinatingOperationStarted、markPrimaryOperationStarted、markReplicaOperationStarted等记账入口,返回Releasable用于请求结束时释放记账 token 并评估吞吐量; - ShardIndexingPressureSettings.java:特性开关与主/次参数配置;
- ShardIndexingPressureMemoryManager.java:分片限额的增减与动态调整;
- ShardIndexingPressureStore.java:hot/cold 双 store 维护各分片 tracker;
- ShardIndexingPressureTracker.java:按 coordinator、primary、replica 三个角色分别维护
OperationTracker,内部再细分为StatsTracker(字节/请求数)、PerformanceTracker(延迟/吞吐量)、RejectionTracker(拒绝计数)。
工作原理与决策流程
发布说明归纳了该特性的关键能力:
- 每个分片、每个节点角色(coordinator、primary、replica)的索引任务性能的粒度化跟踪;
- 更智能的拒绝:只丢弃指向问题索引/分片的请求,其他分片继续服务(拒绝公平性);
- 拒绝阈值由可配置参数(如节点内存上限)与动态参数(如延迟上升、吞吐量下降)共同决定;
- 节点级与分片级索引压力统计通过 stats API 暴露;
- 索引压力统计与插件集成,为指标可见性与未来自动调优铺路;
- 提供 tuning 旋钮调整控制拒绝的关键性能阈值;
- 支持 shadow-mode 与 enforced-mode 两种运行模式:shadow-mode 下仅发布内部拒绝拆解指标、不执行实际拒绝。
结合 ShardIndexingPressureMemoryManager.java 的类注释,其决策逻辑可概括为两阶段:
- 主参数(Primary Parameter,内存占用):若某分片已分配的内存限额被突破,但节点整体内存占用尚未超过
shard_indexing_pressure.primary_parameter.node.soft_limit(默认 0.7),则内存管理器直接上调该分片限额,不做更深层评估; - 次参数(Secondary Parameter,性能退化):若分片限额被突破且节点整体占用已超过软上限,则进一步评估两个次参数来判定分片是否处于"受压(duress)"状态:
- 吞吐量退化(ThroughputDegradationLimitsBreached):滑动窗口平均吞吐量相对历史平均吞吐量放大超过退化因子阈值即判定违规;
- 最近成功请求超时(LastSuccessfulRequestDurationLimitsBreached):距上次成功请求完成的时间超过最大超时阈值,且 outstanding 请求数超过上限时判定违规。
内存管理器还会根据分片利用率(currentShardBytes / shardLimits)落在operating_factor.lower/optimal/upper的哪个区间,动态调高或调低分片限额,使新限额保持在最优区间内。从 ShardIndexingPressure.java 的shouldRejectRequest方法可见最终判定规则:nodeLevelLimitBreached || (shardLevelLimitBreached && enforced)——节点级违规必然拒绝,分片级违规仅在 enforced-mode 下才真正拒绝。
完整的可配置参数表(源码级)
以下参数与默认值均直接取自 1.2.0 对应的源码实现(当前仓库 ShardIndexingPressureSettings.java 与 ShardIndexingPressureMemoryManager.java),均为节点级(NodeScope)动态设置,可通过集群设置 API 在线调整:
| 参数 | 默认值 | 说明 |
|---|---|---|
shard_indexing_pressure.enabled | false | 分片级索引压力总开关,关闭时退化为纯节点级核算 |
shard_indexing_pressure.enforced | false | false为 shadow-mode(只记录拒绝指标不实际拒绝);true为 enforced-mode(执行真实拒绝) |
shard_indexing_pressure.primary_parameter.node.soft_limit | 0.7 | 节点软上限(占节点内存限额的比例),超过后开始评估次参数 |
shard_indexing_pressure.primary_parameter.shard.min_limit | 0.001 | 每个分片的基础限额下限,初始化为节点限额的 1/1000 |
shard_indexing_pressure.operating_factor.lower | 0.75 | 分片利用率下边界,低于此值下调分片限额 |
shard_indexing_pressure.operating_factor.optimal | 0.85 | 分片利用率最优区间参考值 |
shard_indexing_pressure.operating_factor.upper | 0.95 | 分片利用率上边界,高于此值上调分片限额 |
shard_indexing_pressure.secondary_parameter.throughput.request_size_window | 2000 | 吞吐量评估采样的最近 N 个请求窗口大小 |
shard_indexing_pressure.secondary_parameter.throughput.degradation_factor | 5.0(下限 1.0) | 吞吐量退化因子,滑动窗口平均吞吐量相对历史平均放大超过该倍数判定退化;replica 的退化阈值按 1.5 倍放大 |
shard_indexing_pressure.secondary_parameter.successful_request.elapsed_timeout | 300000ms(5 分钟) | 距上次成功请求的最大超时时间 |
shard_indexing_pressure.secondary_parameter.successful_request.max_outstanding_requests | 100 | 触发超时判定的最大 outstanding 请求数 |
需要特别说明的两条派生规则(见 ShardIndexingPressureSettings.java):
- primary/coordinating 分片基础限额 = 节点限额 ×
shard.min_limit; - replica 分片基础限额 = primary 分片基础限额 ×1.5。
Shadow-Mode 与 Enforced-Mode 的落地细节
从 ShardIndexingPressure.java 可以看到 shadow 模式的精确语义:在 shadow 模式下,即便某请求"本应被拒绝"(shard 级违规),它依然会被正常处理,并且不会计入动态拒绝参数(吞吐量、延迟等),从而避免"影子拒绝"污染性能基线;只有真正执行的请求才参与性能评估。而节点级违规在两种模式下都会实际拒绝(shouldRejectRequest中nodeLevelLimitBreached不依赖 enforced 开关)。
被拒绝时,rejectShardRequest 会抛出OpenSearchRejectedExecutionException,错误信息同时携带分片与节点两级的字节明细(shard_total_bytes、shard_operation_bytes、shard_max_coordinating_and_primary_bytes、node_total_bytes等),便于运维定位是哪个分片、哪类操作(coordinating/primary/replica)触发了拒绝。
统计 API 与可观测性
分片级索引压力统计通过shardStats(ShardIndexingPressure.java)暴露,支持按统计标志位返回三类视图:
- top 指标:仅节点级汇总(节点限额违规拒绝数、最近成功请求违规拒绝数、吞吐量退化拒绝数);
- hot store 明细:当前活跃分片的逐分片统计(
IndexingPressurePerShardStats); - cold store 明细:已不再活跃但保留历史的分片 tracker 统计。
聚合统计中区分了三种拒绝原因计数(见 ShardIndexingPressureMemoryManager.java):totalNodeLimitsBreachedRejections、totalLastSuccessfulRequestLimitsBreachedRejections、totalThroughputDegradationLimitsBreachedRejections,让运维可以直接判断压力来源是内存不足、请求卡死还是吞吐退化。
源码与测试印证
该特性的开发按功能拆分为 10 个渐进式 PR(发布说明原文):Settings(#716)、Tracker(#717)、IndexingPressure 重构(#718)、Store(#838)、MemoryManager(#945)、框架级构造与 Stats(#1015)、编排服务 IndexingPressureService(#1084)、Transport Action 管道接入(#1113)、REST 端点指标(#1171)、集成测试(#1198)。当前仓库中对应测试包括:
- ShardIndexingPressureTests.java
- ShardIndexingPressureMemoryManagerTests.java
- ShardIndexingPressureSettingsTests.java
- ShardIndexingPressureStoreTests.java
- ShardIndexingPressureConcurrentExecutionTests.java
- IndexingPressureServiceTests.java
- TransportWriteActionForIndexingPressureTests.java
并发与序列化方面,1.2.0 还修复了分片索引压力相关的两个测试问题:将节点属性检查从集群服务初始化改为版本更新检查(#1398),并降低了并发测试的并发度以消除 flaky(#1361/#1397)。
引擎插件扩展机制:Translog 删除策略与 EngineConfig 覆盖
自定义 Translog 删除策略
发布说明中"Add extension point for custom TranslogDeletionPolicy in EnginePlugin (#1404) (#1424)"描述了新的插件扩展点:实现EnginePlugin接口的插件可以提供自定义的TranslogDeletionPolicy,使插件能在不替换整个引擎的情况下定制 translog 清理行为。当前仓库 EnginePlugin.java 中对应方法为:
default Optional<TranslogDeletionPolicyFactory> getCustomTranslogDeletionPolicyFactory() { return Optional.empty(); }TranslogDeletionPolicyFactory(TranslogDeletionPolicyFactory.java)是一个函数式接口:
@FunctionalInterface public interface TranslogDeletionPolicyFactory { TranslogDeletionPolicy create(IndexSettings settings, Supplier<RetentionLeases> supplier); }插件的工厂方法接收索引设置与 retention lease 供应器,返回自定义删除策略。默认实现由 DefaultTranslogDeletionPolicy.java 提供。注意其限制:同一集群中只能有一个插件覆盖该策略,若多个插件同时覆盖会抛出IllegalStateException(该约束同时体现在接口 Javadoc 与 release notes 中)。
配套变更包括:
minTranslogGenRequired抽象化(#1456/#1478):配合TranslogDeletionPolicy扩展点,将该方法在基类中改为抽象,由子类实现,默认实现下沉到DefaultTranslogDeletionPolicy;- 移除 retention lease 剪枝的废弃设置与逻辑(#1416/#1471):删除此前为实验功能(#1100)添加的按 retention lease 剪枝 translog 的设置与实现,转而支持自定义
TranslogDeletionPolicy扩展点; - 恢复弃用标记(#1294):
INDEX_PLUGINS_REPLICATION_TRANSLOG_RETENTION_LEASE_PRUNING_ENABLED_SETTING曾被移除弃用标记,本版本将其加回弃用状态,以便该设置在下一个 minor 版本迁移到插件内——升级到 1.2.0 的集群如果仍在使用该设置,会收到弃用警告。
EngineConfig 扩展点:EngineConfigFactory
另一项引擎扩展是"Add EngineConfig extensions to EnginePlugin (#1387) (#1401)":通过新的EngineConfigFactory机制,插件可覆盖EngineConfig中的部分配置(如CodecService、TranslogConfig),而无需整体覆盖 Engine(整体覆盖引擎仅允许单个插件且约束更严)。EngineConfigFactory基于插件提供的覆盖项生产新的EngineConfig实例,未覆盖的配置沿用默认值。这为插件提供了"更高保真度"的引擎行为定制能力。
依赖与底层库升级
1.2.0 对底层依赖做了一轮集中升级,主要集中在安全修复与版本统一:
| 依赖 | 目标版本 | 相关提交 |
|---|---|---|
| Lucene | 8.10.1 | Upgrade to Lucene 8.10.1 (#1440) (#1459) |
| gson | 2.8.9 | Upgrading gson to 2.8.9 (#1541) (#1546) |
| Jackson | 2.12.5 | Update Jackson to 2.12.5 (#1247) (#1270) |
| Netty | 4.1.69.Final | Upgrading netty version to 4.1.69.Final (#1363) (#1382) |
| Mockito | 3.12.4 | Replace securemock with mock-maker, update Mockito to 3.12.4 (#1332) (#1354),并统一仓库内 mockito 版本(#1410/#1435) |
| Hadoop(hdfs 插件) | 升级 + htrace-core4 4.1.0 | Upgrade hadoop dependencies for hdfs plugin (#1335) (#1369),后续再次升级(#1466/#1485) |
| Azure Storage SDK | v12 | repository-azure 插件改用 Azure Storage SDK v12 for Java (#1302) (#1409) |
安全方面值得重点说明:移除 reindex 中使用的旧 ES 库(#1359/#1497)——由于 CVE 风险,删除了 reindex 功能依赖的 ES 库 0.90 与 1.76 版本;同时"Upgrading dependencies (#1491) (#1495)"等提交也属于常规依赖翻新。升级到 1.2.0 时,建议关注这些依赖变更对插件编译期与运行期的兼容性影响。
构建、质量与可移植性改进
Spotless 与 Checkstyle 收敛
1.2.0 期间将 Spotless 格式检查逐步铺开到全仓库各模块,并对部分模块从 Checkstyle 中排除(避免双重检查冗余):
- server 模块(#1380/#1391)、client 模块(#1392/#1414)、plugins 模块(#1417/#1423)、libs 模块(#1428/#1434)、modules 模块(#1442/#1453)、test 子项目(#1479)、rest-api-spec 模块(#1462/#1472)、plugins 的 spotless 检查(#1488/#1489),以及 Checkstyle 清理(#1370/#1492)。
这意味着 1.2.0 起,参与这些模块的代码提交需要满足统一的格式化规范,CI 中spotlessCheck/checkstyle会成为硬性门槛。
JaCoCo 代码覆盖率
"Add support to generate code coverage report with JaCoCo (#1236)"为仓库引入了 JaCoCo 覆盖率支持,具体包括:
- 在根项目及所有子项目(经 BuildPlugin)应用 JaCoCo Gradle 插件;
- 新增 3 个 Gradle 任务:
codeCoverageReport:全部测试覆盖率;codeCoverageReportForUnitTest:仅单元测试;codeCoverageReportForIntegrationTest:仅集成测试;
codeCoverageReport任务被挂接到check任务,保证每次构建默认执行覆盖率检查;- 清理了启用 Java Security Manager 时为 JaCoCo 文件赋权的过时逻辑。
开发者可通过./gradlew codeCoverageReport查看当前分支的测试覆盖率报告。
平台支持:Windows 与 FreeBSD
- Windows 构建修复(#1412/#1420):更新开发者指南补充 Windows 专属说明、修正 Windows 任务名、改用 Docker Desktop 安装、定位 docker-compose 的 Windows 默认位置;
- FreeBSD 构建支持(#1091/#1374):允许在 FreeBSD 上构建并成功跑通
./gradlew publishToMavenLocal -Dbuild.snapshot=false(该命令用于 CI 中构建插件)。文档说明在 FreeBSD 上需先安装 JDK 并配置环境:
sudo pkg install openjdk14 export JAVA_HOME=/usr/local/openjdk14/ export PATH=$JAVA_HOME/bin:$PATH- 运行时 JDK 配置澄清(#1372):修订 DEVELOPER_GUIDE.md,澄清 JDK 使用方式并修复运行时 JDK 配置的小问题。
另外两处 JVM/运行相关改进:调整 CodeCache 大小以消除 JVM 警告(乃至崩溃)(#1426/#1432),以及节点统计中新增 Heap after GC 指标(#1265/#1309),后者让运维可以通过 nodes stats API 观察 GC 之后的堆使用量。
重要缺陷修复
发布说明中的[BUG]前缀提交集中体现了本版本在稳定性上的投入:
- SymbolicLinkPreservingUntarTransform 在 Windows 上失败(#1433/#1439):修复符号链接保持型解压在 Windows 平台的兼容性问题,直接影响 Windows 上插件与发行包的安装;
- ConcurrentSnapshotsIT#testAssertMultipleSnapshotsAndPrimaryFailOver 间歇性失败(#1311/#1322):修复快照与主分片故障转移并发场景下的 flaky 测试;
- NodeStatsTests.testSerialization 失败(#1399):修复
org.opensearch.action.admin.cluster.node.stats.NodeStatsTests序列化测试,与新增的 heap-after-GC 字段相关; - 创建第二个 InternalEngine 实例时删除 translog 文件的问题(#1457):使用同一 translog 配置创建第二个引擎实例时会尝试删除已有 translog 文件,修复方案是先关闭第一个实例再创建第二个(该修复消除了确定性测试失败);
- repository-multi-version 的 bwc 测试修复(#1441/#1451);
- 移除不再使用的 Jenkinsfile(#1408/#1411):CI 迁往 opensearch-build 仓库的 Jenkins 流水线。
总结
OpenSearch 1.2.0 通过分片级索引压力把资源治理粒度从节点细化到分片,配合吞吐量与最近成功请求两个次参数,实现了"只拒绝问题分片、不影响健康分片"的公平拒绝策略,并提供了 shadow/enforced 双模式与完整的动态参数旋钮,让运维可以在生产环境中灰度观察后再强制生效;同时通过TranslogDeletionPolicyFactory与EngineConfigFactory两个扩展点,显著降低了插件定制引擎行为的门槛。配合 Lucene 8.10.1 等依赖升级、CVE 清理、Spotless/JaCoCo 质量门槛以及 Windows/FreeBSD 平台修复,1.2.0 是 1.x 分支上一个兼顾新特性、安全性与工程质量的里程碑版本。读者如需深入实践,可结合 DEVELOPER_GUIDE.md 构建本地环境,并通过 ShardIndexingPressureTests.java 等测试了解各参数的预期行为。
- 搜索引擎
- 全文检索
- 可观测性
- 数据分析
【免费下载链接】OpenSearch
🔎 Open source distributed and RESTful search engine.
相关推荐
Envoy 扩展治理全指南:EXTENSION_POLICY 质量门槛、引入流程、移除机制与安全分级实践
Envoy 扩展治理全指南:EXTENSION_POLICY 质量门槛、引入流程、移除机制与安全分级实践 Envoy 以高度可扩展的架构著称,其能力几乎全部以"
云原生服务网格网络微服务3步解锁Android上的Windows应用:Winlator终极输入控制指南
3步解锁Android上的Windows应用:Winlator终极输入控制指南 Winlator是一款革命性的Android应用,它通过Wine和Box86/B
移动开发虚拟化OpenSearch 2.6.0 新特性深度解析:磁盘水位索引阻塞、特性开关与分片护栏
OpenSearch 2.6.0 新特性深度解析:磁盘水位索引阻塞、特性开关与分片护栏 OpenSearch 2.6.0 于 2023 年 2 月 22 日发布
搜索引擎全文检索可观测性数据分析
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考