应用诊断用于对单个应用实例进行深入的运行时剖析,帮助您快速定位 CPU、内存、线程、GC 等资源层面的性能瓶颈。依托增强型探针的自动采集运行时数据能力,用户无需修改业务代码,接入应用即可实现诊断能力。
操作前提
应用类型 | 接入要求 | 支持的诊断能力 |
Java | 接入方案:使用腾讯云增强版 Java 探针接入,探针版本2.3-20250131及以上。 JDK 版本:不推荐使用 Java 8u352以下的 JDK,可能存在 内存崩溃 风险。 操作系统: Linux(x64, arm64)以及 macOS。 运行环境:需要安装 OpenJDK 或其他基于 HotSpot JVM 开发的 JDK,不支持仅安装了 JRE 的环境。 镜像:不推荐使用 Alpine 镜像。Alpine 镜像所包含的 JDK 通常为精简版,可能缺少 JDK 调试符(二进制文件$JAVA_HOME/lib/server/libjvm.so),导致内存采集失败。 | JVM 分析 线程分析 线程池分析 连接池分析 方法执行分析 GC 日志分析 |
Go | 接入方案:使用腾讯云 OpenTelemetry-Go 探针接入,探针版本1.0.1及以上。 Go 版本:1.23及以上。 操作系统:Linux(x64, arm64)。 | |
.Net | 接入方案:使用社区 OpenTelemetry-Dotnet 方案接入。 .Net 版本:.NET 6及以上,不支持 .NET Framework。 |
操作步骤
1. 登录 腾讯云可观测平台。
2. 在左侧菜单栏选择 应用性能监控 > 应用诊断。
3. 在页面顶部的过滤器选择目标地域、业务系统和应用。
4. 在页面左侧的实例列表中选择目标实例。
5. 通过页面右侧的标签页选择诊断能力。
JVM 分析
JVM 分析包括如下图表:
功能 | 描述 |
CPU 利用率 | 展示 JVM 进程 CPU 占用率变化趋势,CPU 利用率根据 JVM 占用的 CPU 处理时间计算而来。 |
Heap 内存利用率 | 展示 JVM 进程 Heap 内存占用率变化趋势,内存利用率 = 实际使用的内存 / JVM 从操作系统申请的最大内存。 |
GC 次数 | 展示 JVM 进程每分钟 GC 次数的变化趋势。 |
平均 GC 耗时 | 展示 JVM 进程 GC 耗时的变化趋势。 |
Heap 内存明细 | 展示 JVM 进程 Heap 内存占用量的变化趋势。 |
Non-Heap 内存明细 | 展示 JVM 进程 Non-Heap 内存占用量的变化趋势。 |
线程状态统计 | 根据不同的线程状态,统计 JVM 线程数量的变化趋势。 |
线程概览统计 | 根据不同的线程类型,统计 JVM 线程数量的变化趋势。 |
Buffer 内存明细 | 展示 JVM 进程缓冲区内存占用量的变化趋势。 |
性能剖析 2.0
性能剖析能力通过智能分析引擎直接输出性能优化建议,并提供增强版火焰图等强大的可视化分析工具,帮助用户快速定位应用性能瓶颈。性能剖析目前支持 Java 和 Go 应用。其中,Java 应用的性能剖析能力基于 async-profiler 技术实现,Go 应用的性能剖析能力基于 pprof 技术实现。腾讯云增强版 OpenTelemetry Java 探针以及腾讯云 OpenTelemetry-Go 探针已经内置性能剖析能力,不依赖任何其他组件,即可以以极低的性能开销,采集剖析数据。
创建采集任务
1. 单击创建采集任务。
2. 在弹出对话框中,根据需要调整采集类型等选项,单击确认。
选项名 | 说明 |
采集类型 | 目前支持 CPU 采样分析和内存采样分析两种采集类型: CPU 采样分析:基于代码块在 CPU 上的执行时间进行剖析。 内存采样分析:基于内存占用进行剖析。 |
采样时长 | 采样时长代表每一次剖析采集数据的时间长度。实际的采集时间会略大于采样时长。 |
目标时间 | 目标时间代表剖析任务创建以后,第一次剖析的执行时间: 立即执行:不等待,立即执行剖析。 指定时间:指定未来24小时内的任意时间点执行剖析。 |
执行次数 | 执行次数代表一个剖析任务将被执行多少次: 单次执行:仅执行一次。 重复执行:剖析任务将按照固定的时间间隔被执行多次,用户需要指定总次数以及间隔时长。 |
剖析结果
采集完成之后,控制台将展示剖析结果。剖析结果包含5个模块,通过不同的标签页进行展示。
模块名 | 说明 |
分析建议 | 分析建议模块基于预置的智能分析引擎输出性能优化建议。针对每条性能优化建议,单击标记,可以对优化建议的价值进行反馈,帮助 APM 提升分析建议的准确度。 |
活跃线程 | 活跃线程模块列出了每条线程被采中的次数,次数越高,代表线程的活跃度越高,可以重点关注。 |
热点函数 | 热点函数模块列出了每个函数被采中的次数,次数越高,代表函数的性能消耗越大,可以重点关注。 |
火焰图 | 火焰图是一种用于可视化程序性能数据的强大工具,是一个由多个矩形条堆积而成的图形,每一层矩形条代表一个函数调用栈中的函数。 |
调用图 | 调用图是一种有向图,用于可视化展示程序中函数之间的调用关系和执行流程。与火焰图比较类似,同样能够体现每个函数在整个程序执行过程中的相对性能开销占比。 |
剖析记录
在有多个剖析结果的情况下,控制台默认展示最新的剖析结果。您可以单击剖析记录,查看其他任务的剖析结果。
Go 应用内存采样分析
针对 Go 应用内存采样分析,APM 将剖析结果通过 Heap(堆)和 Goroutine(协程)两种维度进行展示。两个维度对应的内存空间说明如下:
Heap(堆):多个协程共享的内存空间。
Goroutine(协程):每个协程私有的轻量级内存空间。
其中,热点函数、火焰图和调用图功能支持独立的标签页展示两种维度的剖析结果。分析建议功能将两种维度的剖析结果合并到同一个标签页进行展示,若在某个维度未检测到明显瓶颈,对应的性能优化建议为空。
火焰图
火焰图中水平方向矩形条宽度表示函数性能开销,垂直方向表示调用栈深度。通过观察宽矩形条可快速定位热点函数进行优化,沿垂直方向则可分析调用关系,深入理解执行流程和性能瓶颈。在分析火焰图时,建议从深度最深的函数开始分析。栈最深,出现在火焰图中的位置会越靠近下方,也就是“火苗”的位置(不同于自然界的火焰,在 APM 目前使用的火焰图中,火焰朝向下方)。苗越宽,代表性能上的消耗越大,所以宽火苗往往是引发性能问题的根源。
在火焰图的使用过程中,可以关注如下两类指标数据:
总计占比:表示从函数调用栈的最底层到当前函数(包括当前函数及其所有子函数)的性能开销的占比。这个数据反映了当前函数及其整个调用路径在整个程序执行过程中的相对重要性。
自身占比:指当前函数自身的性能开销,不包括它调用其他函数的性能开销。这个指标可以帮助开发者了解当前函数本身的性能开销,而不受到其调用的其他函数的影响。
单击火焰图中的矩形条,火焰图中将只展示在垂直方向上处于该矩形条调用路径上的矩形条。在这种情况下,该矩形条可以被称为所选区域,而整个应用进程所占的区域可以被称为整体区域(也就是最上层的 root 矩形条)。因此,总计占比和自身占比都可以基于所选区域或整体区域来计算。单击最上层的 root 矩形条,可以回到火焰图的初始状态,在这种情况下,整体区域等同于所选区域。

调用图
调用图和火焰图比较类似,同样能够体现每个函数在整个程序执行过程中的相对性能开销占比。和火焰图不同的是,当一个函数有多个调用方时,调用图更能够体现出函数之间的调用关系。但调用图不能通过矩形的宽度直观展示性能开销,因此大多数场景下,调用图都是配合火焰图来使用。

Arthas 分析
Arthas 能在不修改应用代码的情况下,对应用性能进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。腾讯云增强版 OpenTelemetry Java 探针已经内置 Arthas 能力,关于 Arthas 控制台的操作,请参考 项目主页。
线程分析
线程分析是应用诊断中用于排查线程层面问题的专用页签。它提供了当前应用实例的实时线程快照,帮助您快速定位线程死锁、线程堆积(卡死)、CPU 飙高对应的热点线程等线上问题,将问题直接关联到具体的代码行。
创建采集任务
1. 单击创建采集任务。
2. 在弹出对话框中,单击确认。
分析报告
采集完成后,控制台将展示分析报告,包括如下模块:
模块 | 说明 |
线程列表 | 展示实例当前所有线程的列表,包括线程名称、线程 ID、线程状态等关键信息。 |
死锁分析 | 当实例中存在死锁线程时,控制台将展示死锁涉及的线程及它们相互等待的锁对象关系。 |
线程统计 | 基于线程状态和线程分组统计线程数量。 |
栈帧统计 | 栈帧统计将当前实例中所有线程的调用栈进行归并聚合,把具有相同栈特征的线程合并为一组,并统计每组的线程数量与占比。 |
线程池分析
线程池分析功能可以展示应用核心线程池的各项关键指标,包括最大线程数、核心线程数、活跃线程数、线程池任务数、线程池大小等。
支持的线程池
Apache Dubbo 2.7+
Apache Tomcat 7.0+
OkHttp 2.x/3.x/4.x
指标明细
最大线程数:对应 ThreadPoolExecutor.getMaximumPoolSize()
核心线程数:对应 ThreadPoolExecutor.getCorePoolSize()
活跃线程数:对应 ThreadPoolExecutor.getActiveCount()
线程池大小:对应 ThreadPoolExecutor.getPoolSize()
线程池任务数:对应 ThreadPoolExecutor.getQueue().size()
线程池使用率:活跃线程数/最大线程数*100%
连接池分析
支持的连接池
Apache Druid 1.0+
HikariCP 3.0+
Redisson 3.0+
Jedis 3.0+
Lettuce 5.0+
Apache HttpClient 4.4+
OkHttp 2.x/3.x/4.x
指标明细
以 Druid 连接池为例,APM 会采集如下指标:
当前连接数:对应 DruidDataSource.getPoolingCount() + DruidDataSource.getActiveCount()
最大连接数:对应 DruidDataSource.getMaxActive()
活跃连接数:对应 DruidDataSource.getActiveCount()
空闲连接数:对应 DruidDataSource.getPoolingCount()
等待连接数:对应 DruidDataSource.getWaitThreadCount()
说明:
对于其他连接池,APM 会按照类似的方式采集连接数指标。由于实现机制的差异,部分连接池可能不会上报等待连接数指标。
方法执行分析
方法执行分析通过插桩技术,对指定方法体中不同环节的执行耗时进行逐行统计,帮助您精确定位某个方法内部的性能瓶颈,即到底慢在哪一行代码、哪一个子调用。
创建采集任务
1. 单击创建采集任务,在弹窗中填写以下信息:
字段 | 是否必填 | 说明 |
实例 | 自动 | 当前选中的实例 IP(如10.6.0.156),不可修改。 |
类名 | 必填 | 目标方法所在的全限定类名,如 com.test.web.UserController。 |
方法名 | 必填 | 目标方法名,如 getUser。 |
参数类型 | 选填 | 存在方法重载时,依次输入逗号分隔的参数类型,如 int, java.lang.String。 |
采集次数 | 必填 | 采集调用次数,范围1 - 100次(默认10次)。 |
采集时长上限 | 必填 | 采集最长等待时间,范围10 - 600 秒(默认60秒)。 |
2. 填写完成后单击确认即开始采集。
分析结果
采集完成后,页面展示该方法的逐行执行耗时分析:
字段 | 说明 |
分析记录信息 | 页面顶部展示类名、方法名、实际采集次数与采集时间。 |
调用方法 | 方法体内每一行调用的完整方法签名(含类名与方法名)。 |
行数 | 该调用在源代码中的行号(入口方法本身显示为 -1)。 |
时间轴 | 蓝色条形图,直观展示各行代码的耗时占比;条形越长,耗时越高。 |
结果列表中,入口方法(如 OrderService.generateOrderInfo)以最长的蓝色条显示总耗时,其下逐行列出子调用及其对应的行号与时间轴,方便您直接定位耗时最长的代码行。
GC 日志分析
GC 日志分析功能基于 JVM 输出的 GC Log 排查出有可能影响应用性能的潜在风险。
操作前提
在使用此功能前,先确保 JVM 已经配置了打印 GC 日志相关的启动参数。
打印 GC 日志相关的启动参数
Java 8
启动参数示例如下:
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -Xloggc:gc.log -XX:+UseGCLogFileRotation -XX:GCLogFileSize=20M -XX:NumberOfGCLogFiles=5必填参数:
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -XloggcJava 9 及以上版本
启动参数示例如下:
-Xlog:gc*:file=gc_%p_%t.log:time,pid:filecount=5,filesize=20M或者直接指定 GC 日志绝对路径:
-Xlog:gc*:file=/path/to/gc.log:time,pid:filecount=5,filesize=20M说明:
创建采集任务
1. 单击创建采集任务,在弹出对话框中选择数据时长,数据时长代表从 GC 日志中向前回溯的时间跨度,然后单击确认。
2. 分析总耗时为数秒至5分钟左右,取决于当前选择数据时长内所包含的 GC 日志内容大小,应用性能监控最多可以分析100MB 的 GC 日志数据,超出部分将被截断。
分析报告
分析报告中包含三部分内容:
JVM 信息:目前仅支持在 JDK 8中展示,记录 JVM 版本、启动参数、系统属性等信息。
GC 总览(Summary):在选定时间段有 GC 行为时会展示。需要重点关注日志起始时间、GC 事件总数、GC 吞吐量等信息。GC 吞吐量是衡量 Java 垃圾回收器性能的重要指标,可以尝试不同的垃圾回收器,或者调整垃圾回收器的相关参数,以获取更低的 GC 次数以及更高的 GC 吞吐量。
分析结果(Analysis):在选定时间段有 GC 行为时会展示。分析结果总结了 GC 方面可能存在的问题,并给出了问题的原因以及和解决建议,是分析报告的核心内容,需要重点关注结果分析中的 error 和 warn 部分。
参考如下分析报告:


GC 总览(Summary)
GC 事件总数(GC Events):36586次。该数字偏高,可能意味着应用程序创建了大量的短暂对象,这可能会导致频繁的垃圾回收。
GC 事件类型(Event Types):该时间内产生了 PAR_NEW、CMS_INITIAL_MARK、CMS_CONCURRENT、CMS_REMARK、CMS_SERIAL_OLD 这几种类型的 GC。
并行 GC 事件(Parallel Events):36585次。
串行 GC 事件(Serial Events):1次。
最大堆使用量(Heap Used Max):7092037 K。
GC 后最大堆使用量(Heap After GC Max):6988066 K。这个数字如果接近最大堆使用量(Heap Used Max),可能意味着应用程序的内存使用效率不高,或者存在内存泄漏。
最大堆分配量(Heap Allocation Max):8371584 K。
元空间最大使用量(Metaspace Used Max):167164 K。
GC 后元空间最大使用量(Metaspace After GC Max):167164 K。
最大元空间分配量(Metaspace Allocation Max):1204224 K。
GC 吞吐量(GC Throughput):96%。这意味着应用程序在96%的时间内在执行实际的业务逻辑,而在4%的时间内在进行垃圾回收。GC 吞吐量是一个衡量 Java 垃圾回收器性能的指标,它表示的是应用程序运行的时间占总运行时间的百分比。
最大 GC 暂停时间(GC Pause Max):7.528秒。如果单次 GC 的暂停时间过长,那么可能会影响应用程序的响应时间和延迟。例如,如果应用程序需要在1000毫秒内完成交易,那么任何一次 GC 暂停超过1000毫秒都是不可接受的。优化的方法可能包括使用并发垃圾回收器(如 G1或 CMS),这些垃圾回收器可以在应用程序运行的同时进行垃圾回收,从而减少 GC 暂停时间。
分析结果(Analysis)
分析结果(Analysis)总结了 GC 方面可能存在的问题,并给出了问题的原因以及解决建议,需要重点关注结果分析中的 error 和 warn 部分。例如,在如下示例中,明确指出了 CMS_SERIAL_OLD 垃圾回收器是串行运行的,回收大内存的时候可能会需要非常长的时间,建议通过调整 JVM 参数避免使用串行垃圾回收器。您可以基于分析结果对 JVM 进行调优,并通过应用性能监控的实例监控等功能对比调优后的效果。


运行时分析
运行时分析包括如下图表:
功能 | 描述 |
CPU 利用率 | 展示 CPU 占用率变化趋势,CPU 利用率根据 JVM 占用的 CPU 处理时间计算而来。 |
Heap 内存利用率 | 展示 Heap 内存占用率变化趋势,内存利用率 = 实际使用的内存 / JVM 从操作系统申请的最大内存。 |
GC 次数 | 展示每分钟 GC 次数的变化趋势。 |
Heap 内存明细 | 展示 Heap 内存占用量的变化趋势。 |
线程概览统计 | 根据不同的线程类型,统计线程数量的变化趋势。 |