OpenTelemetry Java 代理通过在同一个 Java 虚拟机(JVM)中运行来为应用程序提供插桩。
像任何其他软件代理一样,Java 代理需要 CPU、内存和网络带宽等系统资源。
代理对资源的使用称为代理开销或性能开销。
OpenTelemetry Java 代理在为 JVM 应用程序提供插桩时对系统性能的影响最小,
但是最终的代理开销取决于多个因素。
一些可能增加代理开销的因素是环境因素,例如物理机器架构、CPU 频率、内存的数量和速度、系统温度以及资源争用。
其他因素包括虚拟化和容器化、操作系统及其库、JVM 版本和供应商、JVM 设置、所监控软件的算法设计以及软件依赖项。
由于现代软件的复杂性以及部署场景的广泛多样性,不可能得出单一的代理开销估算值。
要了解特定部署中任何插桩代理的开销,就必须直接进行实验并收集测量数据。
因此,请将所有有关性能的声明视为一般信息和指南,需要在特定系统中进行评估。
以下章节介绍了 OpenTelemetry Java 代理的最低要求,以及可能影响性能的潜在限制,
还有用于优化和排查代理性能问题的指南。
降低代理开销指南 {#guidelines-to-reduce-agent-overhead}
以下最佳实践和技术可能有助于减少 Java 代理引起的开销。
配置链路采样 {#configure-trace-sampling}
插桩处理的 Span 量可能会影响代理开销。
你可以配置链路采样来调整 Span 量并减少资源使用。
请参阅 采样。
关闭特定插桩 {#turn-off-specific-instrumentations}
你可以通过关闭不需要的或生成过多 Span 的插桩来进一步减少代理开销。
要关闭插桩,请使用 -Dotel.instrumentation.<name>.enabled=false 或OTEL_INSTRUMENTATION_<NAME>_ENABLED 环境变量,其中 <name> 是插桩的名称。
例如,以下选项关闭 JDBC 插桩:-Dotel.instrumentation.jdbc.enabled=false
为应用程序分配更多内存 {#allocate-more-memory-for-the-application}
通过使用 -Xmx<size> 选项增加 JVM 的最大堆大小可能有助于缓解代理开销问题,
因为插桩可以在内存中生成大量短期对象。
将手动插桩精简到所需的程度。 {#reduce-manual-instrumentation-to-what-you-need}
过多的手动插桩可能会引入增加代理开销的低效操作。
例如,在每个方法上使用 @WithSpan 会导致高 Span 量,
这反过来会增加数据噪声并消耗更多系统资源。
配置充足的资源 {#provision-adequate-resources}
确保为插桩和 Collector 提供足够的资源。
内存或磁盘等资源的数量取决于你的应用程序架构和需求。
例如,一种常见的设置是在与 OpenTelemetry Collector 相同的主机上运行插桩应用程序。
在这种情况下,请考虑为 Collector 重新调整资源大小并优化其设置。
请参阅扩容。
Java 代理性能的影响因素 {#constraints-impacting-the-performance-of-the-java-agent}
一般而言,从应用程序中收集的遥测数据越多,对代理开销的影响就越大。
例如,追踪与应用程序无关的方法仍可能产生相当大的代理开销,
因为追踪此类方法的计算成本比方法本身运行的成本还要高。
同样,指标中高基数的标签可能会增加内存占用。
若开启调试日志,也会增加对磁盘的写入操作和内存占用。
某些插桩,例如 JDBC 或 Redis,会产生大量 Span,从而增加代理开销。
有关如何关闭不必要插桩的更多信息,请参见关闭特定插桩。
Java 代理的实验性特性可能会增加代理开销,因为实验性特性的重点是功能而非性能。就代理开销而言,稳定特性更为安全。
代理开销问题的排查 {#troubleshooting-agent-overhead-issues}
在排查代理开销问题时,请执行以下操作:
- 检查最低要求。请参阅前置条件。
- 使用与 Java 代理兼容的最新版本。
- 使用与 JVM 兼容的最新版本。
考虑采取以下措施来减少代理开销:
- 如果应用程序接近内存限制,请考虑为其分配更多内存。
- 如果应用程序使用了所有 CPU,可能需要水平扩展。
- 尝试关闭或调整指标。
- 调整跟踪采样设置以减少 Span 量。
- 关闭不必要的插桩。
- 检查手动插桩是否生成了不必要的 Span。
测量代理开销的指导原则 {#guidelines-for-measuring-agent-overhead}
在您自己的环境和部署中测量代理开销,
能提供有关插桩对应用程序或服务性能影响的准确数据。
以下指导原则阐述了收集和对比可靠的代理开销测量结果的通用步骤。
确定您想要测量的内容 {#decide-what-you-want-to-measure}
不同的应用程序或服务用户可能会注意到代理开销的不同方面。
例如,普通终端用户可能会注意到服务延迟的恶化,而承担高负载工作的资深用户则更关注 CPU 开销。
另一方面,频繁部署的用户(例如由于弹性工作负载)更关心启动时间。
只度量那些确定会影响用户体验的因素,这样你的数据集就不会包含无关信息。
一些测量示例包括:
- 用户平均值、用户峰值和主机平均 CPU 使用率
- 分配的总内存和使用的最大堆内存
- 垃圾回收暂停时间
- 启动时间(毫秒)
- 平均和 95 分位数(p95)服务延迟
- 网络读取和写入平均吞吐量
搭建合适的测试环境 {#prepare-a-suitable-test-environment}
通过在受控测试环境中测量代理开销,可以更好地识别影响性能的因素。
当准备测试环境时,请完成以下操作:
- 确保测试环境的配置与生产环境相似。
- 隔离被测应用程序,确保它与其他可能干扰的服务隔离。
- 关闭或移除应用程序主机上的所有不必要的系统服务。
- 确保应用程序有足够的系统资源来处理测试工作负载。
设计一组贴近真实场景的测试 {#create-a-battery-of-realistic-tests}
设计在测试环境中执行的测试时,应尽可能使其贴近典型工作负载。
例如,如果服务的某些 REST API 端点容易受到高请求量的影响,请创建一个模拟大量网络流量的测试。
对于 Java 应用程序,请在开始测量之前使用预热阶段。
JVM 是一种高度动态的虚拟机,它通过即时编译(JIT)执行大量优化操作。
预热阶段有助于应用程序完成大部分类加载操作,并为 JIT 编译器留出时间执行绝大部分优化。
确保运行大量请求并多次重复测试。
这种重复有助于确保数据样本具有代表性。
包括错误场景在内的测试数据也很重要。
模拟正常工作负载的错误率通常在 2% 到 10% 之间。
测试可能会增加针对可观察性后端和其他商业服务的成本。
请相应地规划测试,或考虑使用替代解决方案,例如自托管或本地运行的后端。
采集可比较的度量数据 {#collect-comparable-measurements}
为识别哪些因素可能影响性能并导致代理开销,应在修改单一因素或条件后,在相同环境中采集度量数据
分析代理开销数据 {#analyze-the-agent-overhead-data}
在收集了多次测试的数据后,可以将结果绘制成图表,或使用统计测试比较平均值以检查显著差异。
请注意,不同的技术栈、应用程序和环境可能会导致不同的操作特性和不同的代理开销测量结果。