开销和性能调优
编辑开销和性能调优
编辑Agent 开销
编辑任何 APM Agent 都会带来一定的开销。以下是一些可能出现开销的不同方面。
延迟
编辑我们非常小心地使关键路径上的代码尽可能轻量级。例如,事件的实际报告是在后台线程上完成的。
平均延迟和较高百分位数的延迟都很低非常重要。这是因为如果 1% 的请求性能非常差,那么低平均延迟就毫无意义。较高延迟峰值的主要来源是垃圾回收暂停和锁争用。
我们非常小心地尽可能减少 Java Agent 中的内存分配。例如,我们不是分配新的对象,而是从对象池中获取它们,并在不再使用它们时将它们返回到池中。有关此过程的更多详细信息,请参见 此处。在报告已记录的事件时,我们直接将它们序列化到对 APM 服务器的请求的输出流中,同时仅依赖于可重用的缓冲区。这样,我们就可以在不分配任何对象的情况下报告事件。我们这样做是为了不增加 GC 的额外工作量,GC 已经忙于清理您的应用程序正在分配的内存。
当我们在线程之间传输事件时,Java Agent 还使用专门的数据结构(LMAX Disruptor 和来自 JCTools 的队列)。例如,从记录事务的应用程序线程到后台报告线程。这是为了避免像使用标准 JDK 数据结构(例如 ArrayBlockingQueue
)那样会遇到的锁争用和虚假共享等问题。
在单线程基准测试中,我们的 Java Agent 的开销在个位微秒 (µs) 量级,直至第 99.99 个百分位数。基准测试是在装有 i7-7700 (3.60GHz) 处理器的 Linux 机器上使用 Oracle JDK 10 运行的。我们目前正在进行多线程基准测试。禁用报头记录后,Agent 分配的字节数少于 1 个字节来记录 HTTP 请求和一个 JDBC (SQL) 查询,包括在后台向 APM 服务器报告这些事件。
CPU
编辑即使 Agent 的大部分工作都在后台进行,序列化和压缩事件以及将它们发送到 APM 服务器实际上也会增加一些 CPU 开销。如果您的应用程序不是 CPU 绑定型,这无关紧要。如果您进行(阻塞)网络 I/O(例如与数据库或外部服务通信),则您的应用程序可能不是 CPU 绑定型。
在 APM 服务器无法处理所有事件的情况下,Agent 将丢弃数据,以免使您的应用程序崩溃。
内存
编辑除非您的堆非常小,否则通常不需要为 Java Agent 增加堆大小。它对对象池和一些大小约为几兆字节的小缓冲区具有相当小且静态的内存开销。
网络
编辑Agent 需要一些网络带宽,因为它需要将记录的事件发送到 APM 服务器。在这里,了解您的应用程序处理多少请求以及您希望记录和存储多少请求非常重要。这可以通过 采样率 进行调整。
调优 Agent 启动
编辑Java Agent 启动时,需要初始化 Agent 的各个组件,连接到 APM 服务器,并检测已加载的任何已配置为进行跟踪的类。这需要一些时间和资源,如果在主线程上同步执行(使用 -javaagent
时为默认设置),则会延迟应用程序启动直到完成。
我们提供了一些选项来调整启动,针对三种启动用例:
- 立即同步 Agent 启动
应用程序需要立即应用检测,而不管启动时间成本如何——通常是因为您不想错过应用程序一开始的任何跟踪/事务,或者某些类型的操作仅在初始化时发生,并且需要在创建第一个实例之前对其进行检测(例如设置预准备语句)。在此用例中,请按照 使用-javaagent
标志进行手动设置 使用-javaagent
命令行标志。 - 最快启动(异步)
应用程序可以接受在应用程序启动之前缺少的检测,也可以接受缺少一些初始跟踪和事务。在此用例中,您可以在启动后使用 使用apm-agent-attach-cli.jar
进行自动设置 连接到应用程序;如果您使用的是-javaagent
命令行标志,则可以通过设置elastic.apm.start_async
属性(自 1.29.0 版起)异步启动 Agent,例如java -Delastic.apm.start_async ...
(在早期版本中可以使用elastic.apm.delay_agent_premain_ms=0
)。 - 最小化同步启动
应用程序需要立即应用检测,但需要最大限度地减少应用程序启动之前的时间。这需要一些权衡:为了减少同步启动时间,需要通过enable_instrumentations
选项最大限度地减少应用的检测数量。在此用例中,您应该确定应用程序监控可以接受的最小检测组集,并使用 配置指南 中详细介绍的enable_instrumentations
配置选项。在应用程序正常终止后,可以在 Agent 日志中找到最小检测集(自 1.29.0 版起)。此外,您可以使用设置为 DEBUG 的日志级别运行 Agent,并在应用程序正常终止后查看 Agent 生成的统计信息。
调优 Agent
编辑Java Agent 提供各种 配置选项,其中一些选项会对性能产生重大影响。为了方便确定哪些选项会影响性能,我们在文档中用 *(性能)* 标记了某些配置选项。
采样率
编辑采样率 是应记录并发送到 APM 服务器的请求百分比。(对于 8.0 之前的服务器,未采样的请求会发送而无需上下文信息,从而减少了传输和存储大小;从 8.0 开始,未采样的请求根本不会发送。)什么是理想的采样率?不幸的是,这个问题没有一个万能的答案。采样取决于您的偏好和您的应用程序。您想要采样的越多,所需的网络带宽和磁盘空间就越多。
需要注意的是,即使您以 100% 的速率进行采样,应用程序的延迟也不会受到 Agent 的太大影响。但是,后台报告线程在序列化和压缩事件时需要做一些工作。
可以通过更改 transaction_sample_rate
(性能) 来更改采样率。
堆栈跟踪收集
编辑如果跨度(例如,捕获的 JDBC 查询)花费的时间超过 5 毫秒,我们将捕获堆栈跟踪,以便您可以轻松找到导致查询的代码路径。堆栈跟踪可能相当长,占用带宽和磁盘空间,并且还需要对象分配。但是,因为我们异步处理堆栈跟踪,所以它几乎不会增加延迟。如果需要,增加 span_stack_trace_min_duration
(性能) 或完全禁用堆栈跟踪收集可以提高一些性能。
记录报头和 Cookie
编辑默认情况下,Java Agent 会记录所有请求和响应报头,包括 Cookie。禁用 capture_headers
(性能) 可以节省分配、网络带宽和磁盘空间。
断路器
编辑启用后,Agent 会定期轮询压力监控器以检测系统/进程/JVM 压力状态。如果任何监控器检测到压力指示,Agent 将变为非活动状态,就像 recording
配置选项已设置为 false
一样,从而将资源消耗降至最低。处于非活动状态时,Agent 将继续轮询相同的监控器以检测压力状态是否已缓解。如果所有监控器都确认系统/进程/JVM 不再处于压力状态,则 Agent 将恢复并恢复完全功能。有关更精细的断路器配置,请参阅 断路器。