事务采样
Elastic Stack 无服务器
在 Elastic Cloud Hosted 中,*APM Server* 从 Elastic APM agents 接收数据并将其转换为 Elasticsearch 文档。在 Elastic Cloud Serverless 中,实际上没有 APM Server 运行,而是由*托管摄取服务*接收和转换数据。
分布式追踪可能会生成大量数据。更多数据可能意味着更高的成本和更多的噪声。采样旨在减少摄取的数据量和分析这些数据所需的工作量 — 同时仍然可以轻松地在应用程序中找到异常模式、检测中断、跟踪错误并缩短平均恢复时间 (MTTR)。
Elastic APM 支持两种类型的采样
Elastic Stack 无服务器
在基于头的采样中,每个追踪的采样决策都是在追踪启动时做出的。每个追踪都有一个明确且相等的采样概率。
例如,采样值 .2
表示事务采样率为 20%
。这意味着只有 20%
的追踪会发送并保留其所有相关信息。其余的追踪将删除上下文信息,以减少追踪的传输和存储大小。
基于头的采样设置起来快速而简单。它的缺点是它是完全随机的 — 有趣的数据可能会仅仅因为偶然性而被丢弃。
请参阅 配置基于头的采样以开始使用。
在分布式追踪中,采样决策仍然是在追踪启动时做出的。每个后续服务都会尊重初始服务的采样决策,而不管其配置的采样率如何;结果是采样百分比与发起服务相匹配。
在图 1 的示例中,Service A
启动了四个事务,采样率为 .5
(50%
)。上游采样决策被尊重,因此即使采样率在 Service B
和 Service C
中被定义且是不同的值,所有服务的采样率都将为 .5
(50%
)。
图 1. 上游采样决策被尊重

在图 2 的示例中,Service A
启动了四个事务,采样率为 1
(100%
)。同样,上游采样决策被尊重,因此所有服务的采样率都将为 1
(100%
)。
图 2. 上游采样决策被尊重

除了设置采样率之外,您还可以指定要使用的*追踪延续策略*。有三种追踪延续策略:continue
、restart
和 restart_external
。
continue
追踪延续策略是默认策略,其行为类似于 分布式追踪部分中的示例。
如果之前的服务没有带有 es
供应商数据的 traceparent
标头,则在 Elastic 监控的服务上使用 restart_external
追踪延续策略以启动新的追踪。如果事务包含接收来自未监控服务的请求的 Elastic 监控服务,这可能会很有用。
在图 3 的示例中,Service A
是一个 Elastic 监控的服务,它以 .25
(25%
) 的采样率启动四个事务。由于 Service B
未被监控,因此在 Service A
中启动的追踪将在那里结束。Service C
是一个 Elastic 监控的服务,它启动四个事务,这些事务以 .5
(50%
) 的新采样率启动新的追踪。由于 Service D
也是 Elastic 监控的服务,因此 Service C
中定义的上游采样决策将被尊重。最终结果将是三个采样的追踪。
图 3. 使用 restart_external
追踪延续策略

在 Elastic 监控的服务上使用 restart
追踪延续策略以启动新的追踪,而不管之前的服务是否具有 traceparent
标头。如果 Elastic 监控的服务是公开的,并且您不希望追踪数据可能被用户请求欺骗,这可能会很有用。
在图 4 的示例中,Service A
和 Service B
是使用默认追踪延续策略的 Elastic 监控的服务。Service A
的采样率为 .25
(25%
),并且该采样决策在 Service B
中被尊重。Service C
是一个使用 restart
追踪延续策略且采样率为 1
(100%
) 的 Elastic 监控的服务。因为它使用 restart
,所以上游采样率在 Service C
中不被尊重,并且所有四个追踪都将在 Service C
中作为新的追踪被采样。最终结果将是五个采样的追踪。

基于头的采样直接在 APM agents 和 SDK 中实现。必须在服务和托管摄取服务之间传播采样率,以便生成准确的指标。
OpenTelemetry 提供了多个采样器。但是,大多数采样器不传播采样率。这会导致不准确的基于 span 的指标,例如 APM 吞吐量、延迟和错误指标。
为了在使用 OpenTelemetry 进行基于头的采样时获得准确的基于 span 的指标,您必须使用 一致的概率采样器。这些采样器在服务和托管摄取服务之间传播采样率,从而生成准确的指标。
OpenTelemetry 并非在所有语言中都提供一致的概率采样器。OpenTelemetry 用户应考虑改用基于尾部的采样。
有关一致的概率采样器的可用性的更多信息,请参阅您喜欢的 OpenTelemetry agent 或 SDK 的文档。
Elastic Stack 无服务器
对基于尾部的采样的支持
仅在写入 Elasticsearch 时才支持基于尾部的采样。如果您使用的是不同的 输出,则*不*支持基于尾部的采样。
在基于尾部的采样中,每个追踪的采样决策都是在追踪完成后做出的。这意味着所有追踪都将针对一组规则或策略进行分析,这些规则或策略将确定它们的采样率。
与基于头的采样不同,每个追踪没有相等的采样概率。因为较慢的追踪比更快的追踪更有趣,所以基于尾部的采样使用加权随机采样 — 因此,具有较长根事务持续时间的追踪比具有快速根事务持续时间的追踪更有可能被采样。
基于尾部的采样的一个缺点是,与基于头的采样相比,它会导致从 APM agents 向 APM Server 发送更多数据。因此,APM Server 将比基于头的采样使用更多的 CPU、内存和磁盘。但是,由于基于尾部的采样决策发生在 APM Server 中,因此从 APM Server 到 Elasticsearch 的数据传输量较少。因此,在您的检测服务附近运行 APM Server 可以减少基于尾部的采样带来的传输成本增加。
请参阅 配置基于尾部的采样以开始使用。
通过基于尾部的采样,会观察所有追踪,并且仅在追踪完成后才做出采样决策。
在此示例中,Service A
启动了四个事务。如果对于结果为 success
的追踪,我们的采样率为 .5
(50%
),而对于结果为 failure
的追踪,采样率为 1
(100%
),则采样的追踪可能如下所示

基于尾部的采样完全在 APM Server 中实现,并且可以与由 Elastic APM agents 或 OpenTelemetry SDK 发送的追踪一起使用。
由于在使用 tailsamplingprocessor 时的 OpenTelemetry 基于尾部的采样的限制,我们建议改用 APM Server 基于尾部的采样。
根据定义,基于尾部的采样 (TBS) 需要在本地临时存储事件,以便在做出采样决策时可以检索和转发它们。
在 APM Server 的实现中,为了更好的可伸缩性,事件会临时存储在磁盘上,而不是在内存中。因此,它需要与 APM 事件摄取速率成比例的本地磁盘存储空间,以及额外的内存来方便磁盘的读写。如果存储限制不足,则会绕过采样。
建议在启用基于尾部采样的同时使用快速磁盘,最好是具有高 I/O 每秒 (IOPS) 的固态硬盘 (SSD)。磁盘吞吐量和 I/O 可能会成为基于尾部采样的性能瓶颈,并影响整体的 APM 事件摄取。磁盘写入量与事件摄取速率成正比,而磁盘读取量与事件摄取速率和采样率成正比。
为了演示性能开销和需求,以下是一些来自独立 APM Server 的参考数字,该服务器部署在 AWS EC2 上,处于满负荷状态,并且仅接收包含跟踪的 APM 事件。这些数字假设 Elasticsearch 没有反压,并且尾部采样策略中的采样率为 10%。
这些数字仅供参考,可能会因采样率、平均事件大小以及每个分布式跟踪的平均事件数量等因素而异。
术语
- 事件摄取率:从 APM Agent 到 APM Server 使用 Intake v2 协议(Elastic APM Agent 使用的协议)的吞吐量,以每秒事件数衡量。
- 事件索引率:从 APM Server 到 Elasticsearch 的吞吐量,以每秒事件数或每秒文档数衡量。请注意,它应该大致等于事件摄取率 * 采样率。
- 内存使用量:在整个基准测试过程中观察到的 APM Server 进程的最大常驻内存集大小 (RSS)。
EC2 实例大小 | TBS 和磁盘配置 | 事件摄取率(事件/秒) | 事件索引率(事件/秒) | 内存使用量(GB) | 磁盘使用量(GB) |
---|---|---|---|---|---|
c6id.2xlarge | 禁用 TBS | 47220 | 47220(100% 采样) | 0.98 | 0 |
c6id.2xlarge | 启用 TBS,EBS gp3 卷,具有 3000 IOPS | 21310 | 2360 | 1.41 | 13.1 |
c6id.2xlarge | 启用 TBS,来自 c6id 实例的本地 NVMe SSD | 21210 | 2460 | 1.34 | 12.9 |
c6id.4xlarge | 禁用 TBS | 142200 | 142200(100% 采样) | 1.12 | 0 |
c6id.4xlarge | 启用 TBS,EBS gp3 卷,具有 3000 IOPS | 32410 | 3710 | 1.71 | 19.4 |
c6id.4xlarge | 启用 TBS,来自 c6id 实例的本地 NVMe SSD | 37040 | 4110 | 1.73 | 23.6 |
EC2 实例大小 | TBS 和磁盘配置 | 事件摄取率(事件/秒) | 事件索引率(事件/秒) | 内存使用量(GB) | 磁盘使用量(GB) |
---|---|---|---|---|---|
c6id.2xlarge | 禁用 TBS | 50260 | 50270(100% 采样) | 0.98 | 0 |
c6id.2xlarge | 启用 TBS,EBS gp3 卷,具有 3000 IOPS | 10960 | 50 | 5.24 | 24.3 |
c6id.2xlarge | 启用 TBS,来自 c6id 实例的本地 NVMe SSD | 11450 | 820 | 7.19 | 30.6 |
c6id.4xlarge | 禁用 TBS | 149200 | 149200(100% 采样) | 1.14 | 0 |
c6id.4xlarge | 启用 TBS,EBS gp3 卷,具有 3000 IOPS | 11990 | 530 | 26.57 | 33.6 |
c6id.4xlarge | 启用 TBS,来自 c6id 实例的本地 NVMe SSD | 43550 | 2940 | 28.76 | 109.6 |
在解释这些数字时,请注意
- 这些指标是相互关联的。例如,当事件摄取率较高时,看到更高的内存使用量和磁盘使用量是合理的。
- 事件摄取率和事件索引率竞争磁盘 IO。这就是为什么有一个异常数据点,其中具有 32GB NVMe SSD 的 APM Server 版本 8.18 显示出比 9.0 更高的摄取率,但更慢的事件索引率。
与版本 8.18 相比,版本 9.0 中的基于尾部采样的实现提供了明显更好的性能,这主要是由于重写的存储层。这个新的实现压缩了数据,并更可靠地清理了过期的数据,从而减少了磁盘、内存和计算资源的负载。这种改进在较慢的磁盘上的事件索引率中尤其明显。在版本 8.18 中,随着数据库的增长,性能下降可能会变得不成比例。
Elastic Stack 无服务器
一个被采样的跟踪会保留所有与其相关的数据。一个未被采样的跟踪会丢弃所有span和transaction数据。1无论采样决定如何,所有跟踪都会保留error数据。
APM 应用程序中的一些可视化,例如延迟,由聚合的 transaction 和 span metrics驱动。 这些指标的计算方式取决于使用的采样方法。
- 基于头部采样:指标基于所有采样的事件计算。
- 基于尾部采样:指标基于所有事件计算,无论它们最终是否被采样。
- 头部和尾部采样都使用:当两种方法一起使用时,指标基于所有被基于头部采样的策略采样的事件计算。
对于所有采样方法,指标都通过基于头部采样的策略的逆采样率进行加权,以提供对总体的估计。 例如,如果您的基于头部采样的采样率为 5%,则每个采样的跟踪都算作 20。 随着延迟的变化增加或基于头部采样的采样率降低,这些计算中的误差水平可能会增加。
这些计算方法确保 APM 应用程序提供尽可能准确的指标,同时考虑到正在使用的采样策略,并且还考虑基于头部采样的采样率来估计完整的跟踪总体。
1 真实用户监控 (RUM) 跟踪是此规则的例外。 利用 RUM 数据的 Kibana 应用程序依赖于 transaction 事件,因此未采样的 RUM 跟踪会保留 transaction 数据 — 仅丢弃 span 数据。
Elastic Stack 无服务器
最佳采样率是多少? 遗憾的是,没有一个通用的答案。 采样取决于您的数据、应用程序的吞吐量、数据保留策略和其他因素。 从 .1%
到 100%
的采样率都被认为是正常的。 您可能会为不同的场景决定一个唯一的采样率。 以下是一些示例:
- 与其他服务相比,流量显着更多的服务可能可以安全地以较低的速率进行采样。
- 比其他路由更重要的路由可能会以更高的速率进行采样。
- 生产服务环境可能比开发环境需要更高的采样率。
- 失败的跟踪结果可能比成功的跟踪更有趣 — 因此需要更高的采样率。
无论上述情况如何,注重成本的客户可能更喜欢较低的采样率。
Elastic Stack 无服务器
有三种方法可以调整 APM Agent 的基于头部采样的采样率:
可以使用 Kibana 中的APM Agent 配置,在每个服务和每个环境的基础上动态更改 transaction 采样率(无需重新部署)。
APM Agent 配置公开了一个 API,可用于以编程方式更改您的 Agent 的采样率。 有关示例,请参阅Agent 配置 API 参考。
每个 Agent 都提供一个配置值,用于设置 transaction 采样率。 有关更多详细信息,请参阅相关 Agent 的文档:
- Go:
ELASTIC_APM_TRANSACTION_SAMPLE_RATE
- Java:
transaction_sample_rate
- .NET:
TransactionSampleRate
- Node.js:
transactionSampleRate
- PHP:
transaction_sample_rate
- Python:
transaction_sample_rate
- Ruby:
transaction_sample_rate
Elastic Stack 无服务器
使用基于尾部采样需要更高的权限。 有关更多信息,请参阅创建基于尾部采样的角色。
使用启用基于尾部采样来启用它。 启用后,跟踪事件会映射到采样策略。 每个采样策略都必须指定一个采样率,并且可以选择指定其他条件。 只有当跟踪事件的所有策略条件都为真时,它才能匹配该策略。
跟踪事件按照指定的顺序与策略匹配。 每个策略列表都必须以默认策略结束 — 该策略仅指定采样率。 此默认策略用于捕获与更严格策略不匹配的其余跟踪事件。 需要此默认策略可确保仅有意的删除跟踪。 如果您启用基于尾部采样并发送一个与任何策略都不匹配的 transaction,APM Server 将拒绝该 transaction,并显示错误 no matching policy
。
请注意,从版本 9.0.0
开始,APM Server 具有无限的存储限制,但当数据库所在的磁盘达到 80% 的使用率时,它将停止写入。 由于限制的计算和实施方式,实际磁盘空间仍可能略微超过此基于磁盘使用率的限制或任何配置的存储限制。
此示例定义了三个基于尾部的采样策略:
- sample_rate: 1
service.environment: production
trace.name: "GET /very_important_route"
- sample_rate: .01
service.environment: production
trace.name: "GET /not_important_route"
- sample_rate: .1
- 对
production
中名称为"GET /very_important_route"
的跟踪进行 100% 采样 - 对
production
中名称为"GET /not_important_route"
的跟踪进行 1% 采样 - 默认策略以 10% 的采样率对所有剩余的跟踪进行采样,例如,不同环境(如
dev
)中的跟踪,或者具有任何其他名称的跟踪
设置为 true
以启用基于尾部的采样。 默认禁用。(bool)
APM Server 二进制文件 | sampling.tail.enabled |
Fleet 管理 | 启用基于尾部采样 |
多个 APM Server 的同步间隔。 应为几十秒或几分钟。 默认值:1m
(1 分钟)。 (duration)
APM Server 二进制文件 | sampling.tail.interval |
Fleet 管理 | 间隔 |
用于将根 transaction 匹配到采样率的标准。
策略将跟踪事件映射到采样率。 每个策略都必须指定一个采样率。 跟踪事件按照指定的顺序与策略匹配。 只有当跟踪事件的所有策略条件都为真时,它才能匹配该策略。 每个策略列表都应以仅指定采样率的策略结束。 此最终策略用于捕获与更严格策略不匹配的其余跟踪事件。 ([]policy
)
APM Server 二进制文件 | sampling.tail.policies |
Fleet 管理 | 策略 |
为与尾部采样策略匹配的跟踪事件分配的存储空间量。 注意:将此限制设置得高于允许的空间可能会导致 APM Server 变得不健康。
值为 0GB
(或等效值)不会设置具体的限制,而是允许 APM Server 将其磁盘使用量与磁盘大小对齐。 APM Server 最多使用本地基于尾部采样数据库所在的磁盘上磁盘大小限制的 80%。 最后 20% 的磁盘将不被 APM Server 使用。 这是推荐的值,因为它会自动随磁盘大小进行缩放。
如果不需要此功能,则可以为用于基于尾部采样的最大磁盘空间设置具体的 GB
值。
如果配置的存储限制不足,它会记录“已达到配置的限制”。 当达到存储限制时,事件将绕过采样并且始终会被索引。
默认值:0GB
。(text)
APM Server 二进制文件 | sampling.tail.storage_limit |
Fleet 管理 | 存储限制 |
应用于与此策略匹配的跟踪事件的采样率。 每个策略中都需要。
采样率必须大于等于 0
且小于等于 1
。例如,sample_rate
为 0.01
意味着将对符合策略的追踪事件的 1% 进行采样。sample_rate
为 1
意味着将对符合策略的追踪事件的 100% 进行采样。(整数)
用于匹配策略的事件的追踪名称。当配置的 trace.name
与追踪的根事务的 transaction.name
匹配时,就会发生匹配。根事务是任何没有 parent.id
的事务。(字符串)
用于匹配策略的事件的追踪结果。当配置的 trace.outcome
与追踪的 event.outcome
字段匹配时,就会发生匹配。追踪结果可以是 success
、failure
或 unknown
。(字符串)
用于匹配策略的事件的服务名称。(字符串)
用于匹配策略的事件的服务环境。(字符串)