Skip to main content

OpenSearch 2.9 的全新体验特性 —— 扩展

· 16 min read

Extensions 是 OpenSearch 2.9 的一个新实验性功能,它允许您扩展 OpenSearch 并在不影响集群可用性的情况下独立扩展工作负载。在本博文中,我们将介绍扩展并将其与插件进行比较。通过使用一个运行高基数异常检测的机器学习算法的 36 节点集群,我们将演示如何实现每个数据节点的成本降低 33%,性能与插件相匹配,并且仅增加了一个扩展节点的成本。

旧的方法:插件

OpenSearch 是 Elasticsearch 7.10 的一个分支,其通过插件提供扩展功能。直到现在,插件一直是扩展 OpenSearch 功能的最佳方式,我们撰写了一篇博文来帮助您了解它们的工作原理。目前,OpenSearch 项目维护着 17 个插件,并且在过去的两年中,我们在开发和运营这些插件时积累了很多经验。在此过程中,我们遇到了现有插件体系结构中的许多瓶颈。

插件在 OpenSearch 引导时被类加载到内存中,因此在 OpenSearch 进程内运行。这导致了以下三个架构问题:

  1. 插件需要与 OpenSearch 进行严格的版本兼容。每次 OpenSearch 核心的补丁版本更改都需要重新编译和重新发布插件。
  2. 插件不是隔离的,因此可能会对 OpenSearch 集群产生致命影响,并且不能独立扩展。
  3. 需要同时管理所有组件的依赖关系,这使得在单个产品分发中包含 20 多个插件变得具有挑战性。

新的方法:扩展

与插件不同,扩展以独立的进程或远程节点运行,是隔离的,并且具有干净、明确定义的接口与 OpenSearch 核心进行交互。这些接口是版本化的(遵循语义化版本规范),并且适用于次要和补丁版本,未来有可能与多个主要版本的 OpenSearch 兼容。

扩展架构如下图所示。有关详情,请参阅扩展设计文档

实验性 SDK 发布

在我们的可扩展性路线图上的第一步是推出一个 SDK,使得扩展 OpenSearch 的体验比使用插件更加简便。今天,我们推出了 Java 版本的 opensearch-sdk-java,该版本与 OpenSearch 2.9 及更高版本兼容。要了解如何启用实验性扩展功能,请参阅开发者指南。

扩展接口在 OpenSearch 的次要和补丁版本中是兼容的,因此在升级到下一个版本的 OpenSearch 2.10 时,无需重新编译、重新部署或重新安装扩展。这些 API 目前包括在扩展中公开 REST 接口的功能,并附带客户端库以与 OpenSearch 集群中的数据进行交互。

SDK 的第一个版本 v0.1.0 在 Maven 下的名称为 org.opensearch.sdk 。你可以从开发者文档开始构建第一个扩展。

我们如何编写第一个扩展?

我们选择将异常检测插件作为第一个要迁移到扩展的插件,因为它的复杂性和对性能的敏感性相结合。

在技术上,异常检测并不是我们的第一个扩展。就像任何探索新领域的人一样,我们创建了一个“Hello World”示例,以展示开始时的简易性,并演示基本接口的使用,而无需涉及真实应用程序的复杂性。然后,我们希望面对迁移到完全成熟、可投入生产的插件的挑战。

大多数插件向 OpenSearch 发出用户数据或集群状态的请求。我们的扩展需要一个 REST 客户端来匹配这种功能。我们最初选择了 OpenSearch Java 客户端。作为一个稳健、基于规范的自动生成的客户端,它似乎是一个理想的选择,特别是考虑到我们未来计划将 SDK 移植到其他编程语言,这些语言都具有类似的客户端。对于新的扩展开发,这仍然是首选的客户端。然而,对于实验性版本,异常检测非常依赖于现有的 NodeClient API,我们发现自己不得不重新编写太多的代码。

Java 高级 REST 客户端,目前是 OpenSearch 核心的一部分,具有几乎相同的接口,但已被提议废弃。我们选择将其用于早期的迁移工作,并决定在 OpenSearch 3.0 或 4.0 中删除它之前不切换到该客户端。这使我们能够最大限度地减少工作量,并通过添加少量的包装类来快速迁移所有 API。

在努力减少工作量的同时,我们实施了一些效率低下的操作。异常检测插件经常使用 OpenSearch 集群状态对象。由于集群状态在 OpenSearch 核心中始终是最新的,因此对于有效地获取信息很有用。然而,在扩展环境中,出于例如查找索引或别名是否存在的目的,多次检索整个集群状态被证明是 是一种资源浪费,导致了许多 API 超时(在我们的初始原型中,创建一个检测器通常需要近 13 秒)。为了解决这个问题,我们使用了现有的设置并针对索引 API 和集群 API 进行了有针对性的调用,将引导时间缩短为不到一秒钟。

有关实施细节和将异常检测作为插件和扩展的差异,请参阅异常检测作为扩展的代码

性能测试

为了以扩展形式测试高基数异常检测(HCAD),我们复制了在此博文中描述的设置,并用 28 个 r5.2xlarge 数据节点(在相同成本下替换 36 个节点),加上一个运行异常检测扩展的 r5.16xlarge 实例。我们分析了 1,000 个历史时间段,每个时间段有 1,000 个实体,生成了 1 百万个结果:

GET /_extensions/_ad/detectors/results/_search
{
"query": {
"range": {
"execution_start_time": {
"gte": 1687456200000,
"lte": 1687456260000
}
}
},
"track_total_hits": true
}
{
...
"hits": {
"total": {
"value": 1000000,
"relation": "eq"
},
...
...
}

为确保稳定的集群性能,插件限制了这些分析速率。经过一些微调(我们将同时检测器任务从 10 个增加到 96 个,并将批处理任务时间间隔从 5 秒减少到 3 秒),扩展版本的异常检测能够在 55 秒内成功完成此分析。这并不完全是一比一的比较,因为之前提到的博文中的测试涉及 100 万个较小的模型 x 1 个时间片生成 100 万个结果(我们需要更多的时间来实现对扩展中实时异常检测的支持)。然而,我们相信一旦扩展能够在该环境中运行,我们应该能够在单个节点上或少量节点上支持 100 万个模型。

由于我们的扩展在远程节点上运行,我们观察到了 API 调用延迟的预期增加。例如,启动/停止检测器的调用从 50-100 毫秒增加到 200-300 毫秒。这些调用是用于设置异常检测的边缘 CRUD 操作。以下图表提供了扩展和插件之间延迟的比较。有关更多信息,请参阅异常检测扩展的性能测试

扩展与插件延迟对比图

性能改进

我们证明将异常检测从插件升级为扩展可以与现有用户的性能相匹配。但我们相信我们可以通过以下三种方式进一步改进:

  1. 使用更便宜的集群 我们发现通过将异常检测编写为扩展,我们可以减少集群的成本,并且仍然能够满足相同的性能要求。因为异常检测不再在数据节点上运行,我们能够将所有内存优化的 r5.2xlarge 节点替换为通用型 c5.2xlarge 节点,从而使历史分析每个数据节点的成本降低 33%,并且只增加了一个扩展节点的成本。

    我们还可以进一步减少数据节点的数量,以优化搜索数据和索引结果。例如,因为原始性能基准测试中的大多数数据节点除了索引结果外几乎没有使用,我们测试了一个只有 24 个 c5.2xlarge 数据节点的集群,再加上 1 个 r5.16xlarge 的扩展节点,进一步减少了 33%。我们相信通过进一步试验和微调,您可以找到更优化的混合方案,具体取决于集群的其他资源需求。

  2. 增加索引吞吐量 虽然我们尚未进行此实验,但我们相信您可以通过增加分片来进一步独立微调集群,从而在索引异常检测结果时获得更好的吞吐量。

  3. 提高历史结果生成速率 异常检测的历史 HCAD 限制了历史时间段结果的速率,限制了异常检测使用堆的一半,并将检测的最大限制设置为 10 个并行线程,以保护集群不会超出极限。您可以通过添加更多的 CPU 或 RAM,与集群的其他部分独立交换空间,或者横向扩展扩展节点来提高这些限制。

结论

通过将所有资源正确配置到正在执行的任务,扩展可以节省成本并提高性能。在我们的测试中,我们不需要将整个集群都设置为内存优化服务器,以执行历史异常检测,因此每个数据节点的成本降低了 33%。

作为插件,异常检测与 OpenSearch I/O 共享 CPU 和内存,并且必须限制自己的资源消耗,以确保集群的稳定性。例如,在异常检测插件 HCAD 测试中,模型被限制在使用堆的一半,堆本身又是节点内存的一半。在异常检测扩展场景中,可以将堆缩放以使用服务器大部分内存,并充分利用专用于异常检测任务的 64 个虚拟 CPU。

其他现有的插件也可以从这种模式中受益,包括所有具有内存或 CPU 限制的插件,例如 ML Commons、k-NN 和 Reporting。这项新技术还允许实现新的资源密集型扩展,例如重排、数据转换、大数据处理或视频索引等。

下一步

我们对可扩展性取得的进展和早期性能基准测试结果感到非常高兴。未来,短期内我们将把重点转向使用可扩展性项目的经验,来实现 OpenSearch 机器学习(ML)产品的可扩展性。我们的目标是提供基于规范的应用程序框架,让用户能够在 OpenSearch 中创建无代码的 ML 驱动应用程序,并最终提供一种简单的一键方式,让用户可以测试、构建和部署 ML 驱动的应用程序。此外,在我们决定发布这个实验性功能和 SDK 的普遍可用版本之前,我们希望得到您的反馈。阅读扩展文档后,请尝试实现一个实验性扩展,并通过在 OpenSearch 论坛上发布反馈或在 opensearch-sdk-java 存储库中开启问题来告诉我们您的意见。我们迫不及待地希望听到您的声音!

以上就是关于 OpenSearch 2.9 中扩展功能的介绍以及与插件的比较,以及对异常检测插件迁移到扩展的经验分享和性能测试结果。OpenSearch 团队致力于不断改进和扩展 OpenSearch,提供更好的性能和更灵活的功能,以满足用户的需求。如果您对 OpenSearch 感兴趣,我们鼓励您尝试使用扩展功能并提供反馈,以帮助改进这一功能。谢谢您的阅读!