在当今快节奏的数字环境中,监控和优化应用程序性能的能力对于努力提供卓越用户体验的组织至关重要。在 Elastic,我们认识到为用户群提供一个可靠的可观测性平台的重要性,该平台可随着您每天载入数千个产生 TB 级数据的服务而扩展。我们一直在幕后努力增强我们的解决方案,以满足即使是最大规模部署的需求。
在这篇博文中,我们很高兴分享我们在改进 Elastic APM 的 UI 性能方面取得的重大进展。当交互式总结大量数据以提供整个企业级服务库存的性能概述时,保持流畅的用户界面可能是一个挑战。我们想向我们的客户保证,我们已经听取了意见、采取了行动,并进行了显著的架构更改,以提高我们解决方案的可扩展性和成熟度。
架构增强
我们的旅程始于 7.x 系列,当时我们注意到对原始事务数据进行临时聚合会给大规模环境中的 Elasticsearch® 带来很大压力。从那时起,我们开始在数据提取期间将事务预先聚合到事务指标中。这有助于保持 UI 的性能相对稳定。无论受监控的应用程序有多繁忙,以及它创建了多少事务事件,我们都只是查询以恒定速率存储的预聚合指标。我们在7.15中默认启用了基于指标的 UI。
但是,当在较长时间范围内显示大量服务清单时,需要聚合的指标数据点数量仍然可能非常大,从而导致性能问题。我们还为每个不同的维度集创建一个时间序列。维度包括元数据,例如事务名称和主机名。我们的文档包括所有可用维度的完整列表。如果存在大量唯一的事务名称,这可能是由不正确的检测造成的(有关更多详细信息,请参阅文档),这将创建许多单独的时间序列,在请求服务整体性能的摘要时需要聚合这些时间序列。添加到 APM 代理配置的全局标签也会作为维度添加到这些指标中,因此它们也会影响时间序列的数量。有关更多详细信息,请参阅下面的常见问题解答部分。
在 8.7 和 8.8 版本中,我们通过以下架构增强解决了这些挑战,这些增强旨在减少 Elasticsearch 需要搜索和动态聚合的文档数量,从而加快响应时间
- 将事务指标预先聚合到服务指标中。我们不是为每个用户请求动态聚合为每个单独事务名称创建的所有不同时间序列,而是在数据提取期间为每个服务预先聚合摘要时间序列。根据服务具有的唯一事务名称数量,这将 Elasticsearch 需要查找和聚合的文档数量减少了通常 10 到 100 倍。这对于服务清单和服务概览页面特别有用。
- 将所有指标预先聚合到不同的粒度级别。 APM UI 根据选定的时间范围选择最合适的粒度级别。除了以 1 分钟粒度存储的指标外,我们还以 10 分钟和 60 分钟粒度级别汇总和存储指标。例如,在查看 7 天的时间段时,会查询 60 分钟数据流,而不是 1 分钟数据流,从而使 Elasticsearch 需要检查的文档减少 60 倍。这确保即使在查看较大的时间范围时,所有图表也能快速呈现。
- 对我们聚合指标的每个服务唯一事务数量的保护措施。我们的代理旨在保持事务名称的基数较低。但在实际使用中,我们看到一些服务有大量的唯一事务名称。这过去会在 UI 中导致性能问题,因为 APM Server 会创建许多 UI 在查询时需要聚合的时间序列。为了防止 APM Server 在聚合每个唯一事务名称的大量时间序列时耗尽内存,当达到时间序列数量的限制时,指标会在未聚合的情况下发布。这导致需要在查询时聚合的大量单独的指标文档。为了解决这个问题,我们引入了一个系统,当达到限制时,我们会为每个服务在一个专用的溢出桶中聚合指标。有关更多详细信息,请参阅我们的文档。
文档计数减少的确切因素取决于各种条件。但是,为了了解典型场景,如果您的服务平均有 10 个实例,没有特定于实例的全局标签,每个实例有 100 个唯一的事务名称,并且您正在查看可以利用 60 分钟粒度的时间范围,您会看到 Elasticsearch 需要聚合的文档减少 180,000 倍(10 个实例 x 100 个事务名称 x 60 分钟 x 3,因为我们也在折叠 event.outcome 维度)。虽然 Elasticsearch 聚合的响应时间与文档数量的缩放比例并非完全线性,但它们之间存在很强的相关性。
常见问题解答
升级到最新版本后,我的旧数据加载速度也会更快吗?
更新到 8.8 不会立即使 UI 更快。由于这些改进是由 APM Server 在数据提取期间进行的预聚合驱动的,因此只有新数据才会从中受益。因此,您还应该确保更新 APM Server。UI 仍然可以显示使用旧版本的堆栈提取的数据。
如果 UI 基于指标,我仍然可以使用自定义标签进行切片和切块吗?
高基数分析是 Elastic 可观测性的一个重要优势,并且这种对预聚合指标的关注不会以任何方式损害这一点。
用户界面实现了一种精巧的回退机制,根据应用的过滤器,使用服务指标、事务指标或原始事务事件。例如,我们不会为每个 user.id 创建指标。但是您仍然可以按 user.id 筛选数据,届时用户界面将使用原始事务事件。当按预聚合指标中不可用的维度进行筛选时,您很可能正在查看一小部分数据,因此对原始数据进行聚合通常非常快。
请注意,添加到 APM 代理配置中的所有全局标签都属于预聚合指标的维度,但 RUM 除外(详见此问题)。
我可以在自定义仪表板中使用预聚合指标吗?
可以!如果您使用Lens并选择“APM”数据视图,则可以根据您需要的详细程度,筛选 metricset.name:service_transaction 或 metricset.name:transaction。事务延迟捕获在 transaction.duration.histogram 中,成功结果和失败结果存储在 event.success_count 中。如果您不需要值的分布,也可以选择 transaction.duration.summary 字段进行指标聚合,这样会更快。如果要计算失败率,这里有一个Lens 公式:1 - (sum(event.success_count) / count(event.success_count))。请注意,此处仅支持 1 分钟的粒度。
额外的指标会影响存储吗?
虽然我们存储的指标比以前更多,并且我们以不同的粒度级别存储所有指标,但我们通过为所有指标数据流启用合成源来抵消了这一点。我们甚至增加了粗粒度级别指标的默认保留期,因此 60 分钟汇总数据流现在存储 390 天。有关不同指标数据流的更多信息,请参阅我们的文档。
APM Server 可以聚合的时间序列数量是否有限制?
APM Server 在内存中执行预聚合,这速度很快,但会消耗大量内存。存在一些限制来保护 APM Server 免于耗尽内存,从 8.7 版本开始,大多数限制默认情况下会随可用内存扩展,这意味着向 APM Server 分配更多内存将使其能够处理更多独特的预聚合组,如服务和事务。这些限制在APM Server 数据模型文档中进行了描述。
在 APM Server 的路线图中,我们计划转向基于 LSM 的方法,在这种方法中,预聚合将在磁盘的帮助下执行,以减少内存使用。这将使 APM Server 能够更好地随输入大小和基数进行扩展。
使用预聚合时,一个常见的陷阱是将实例特定的全局标签添加到 APM 代理。这可能会耗尽聚合限制,并导致指标聚合到溢出桶下,而不是相应的服务。因此,请确保遵循最佳实践,仅将有限的全局标签集添加到特定服务。
验证
为了验证新架构的有效性,并确保数据的准确性不受负面影响,我们准备了一个测试环境,其中我们在 14 天的时间跨度内每分钟生成 35,000+ 个事务,最终产生约 8.5 亿个文档。
我们使用不同的时间范围(1 天、7 天、14 天)测试了驱动服务清单、服务概览和事务详细信息的查询。总体而言,我们看到了数量级的改进。特别是,受益于使用粗粒度指标以及预聚合服务指标的更大时间范围的查询,响应时间大幅缩短。
我们还验证了对于更大的时间范围使用更粗粒度的指标时,准确性没有损失。
每个环境的表现都会略有不同,但我们相信,响应时间的显著改进将很好地转化为更大规模的设置。
计划的改进
如常见问题解答部分所述,事务指标的时间序列数量可能会快速增长,因为它是多个维度的乘积。例如,如果一个服务在 100 个主机上运行,并且有 100 个事务名称,每个事务名称都有 4 个事务结果,那么 APM Server 需要跟踪该服务的 40,000 个(100 x 100 x 4)不同的时间序列。对于具有 64GB 主内存的 APM Server 来说,甚至会超过每个服务的 32,000 个的最大限制。
因此,用户界面将在服务概览页面中显示“剩余事务”的条目。这会在服务达到限制后跟踪服务的事务指标。因此,您可能看不到服务的所有事务名称。也可能列出了所有不同的事务名称,但该服务的某些实例的事务指标会合并到“剩余事务”类别中。
我们目前正在考虑重组指标的维度,以避免事务名称和特定于服务实例的维度(例如主机名)的组合导致时间序列的爆炸式增长。请继续关注更多详细信息。
结论
我们在过去版本中提供的架构改进在我们的用户界面的可扩展性和响应能力方面提供了一个阶跃函数。我们不是在用户浏览用户界面时必须即时聚合大量数据,而是在数据传入时预聚合最常见查询的结果。这确保了我们在用户提出最常见问题之前就准备好答案,同时仍然能够回答临时问题。
我们很高兴继续支持我们的社区成员,因为他们正在他们的成长旅程中突破界限,为他们提供一个强大而成熟的平台,可以毫不费力地处理最大的工作负载。Elastic 致力于实现其使命,使每个人都能找到重要的答案。来自所有数据。实时。大规模。
本文中描述的任何特性或功能的发布和时间安排仍由 Elastic 自行决定。任何当前不可用的特性或功能可能无法按时交付或根本不交付。