图片
注:SysOM 是阿里云操作系统控制台的运维组件。

背景

进程热点某个进程或进程中的某些部分(如函数、代码段、线程等)占用大量系统资源(如 CPU 时间、内存、磁盘 I/O 等),或者执行频率非常高,从而成为系统性能瓶颈或资源消耗的重点区域。它是性能分析和优化中的一个重要概念,帮助开发者和运维人员快速定位系统中的关键问题区域。

进程热点追踪是性能分析中的关键概念,通过性能分析工具和可视化手段(如火焰图),可以快速定位系统中的性能瓶颈和资源消耗热点,从而为优化和故障排查提供有力支持。在现代复杂的系统环境中,掌握进程热点分析技能对于提升系统性能和稳定性至关重要。

业务痛点解析

痛点一:进程性能瓶颈导致业务异常

在现代复杂的云原生和容器化部署环境中,业务系统面临着诸多性能瓶颈带来的痛点。一方面,进程性能瓶颈可能导致系统响应时间显著增加,尤其是在高并发场景下,用户请求处理速度变慢,直接影响用户体验。另一方面,某些进程占用大量系统资源(如 CPU、内存),导致系统负载过高,甚至出现服务不可用的情况。进程性能瓶颈无疑是导致业务异常的关键因素之一。而通过进程热点追踪技术,可以有效定位和解决这些问题。进程热点追踪能够通过生成调用图谱和热点分析,直观展示资源消耗较高的部分,帮助开发和运维人员快速识别性能瓶颈。

痛点二:偶发抖动,根因难以追溯

线上问题往往具有偶发性或短暂性,当问题出现时,等到手动执行perf等诊断工具,可能已经错过了最佳诊断时机,无法捕捉到问题发生时的第一现场。因此,我们通过一系列先进的技术手段,实现了进程热点追踪的常态化采集。这一采集机制对系统资源的消耗极低,几乎不会对正常业务运行产生影响。借助 SysOM 进程热点追踪功能,当业务出现历史抖动或其他异常时,无需人工手动登录机器或实时值守,即可随时查看过往时间段内进程的运行状态,快速定位问题根源,提升运维效率。

痛点三:定位周期长,业务潜在问题任然存在

在面对业务问题时,由于缺乏有效的分析手段,很多情况下只能采用临时的“止血”方案来缓解症状,但问题的根源并未得到解决,业务问题仍然存在。由于无法清晰地了解问题的根因,系统可能长期处于不稳定状态,甚至濒临崩溃的边缘。为此,SysOM 进程热点追踪功能提供了丰富的分析手段。它不仅涵盖了传统的技术方法,如调用链分析、对比分析等,还引入了先进的 AI 智能诊断功能。AI 智能诊断融合了过往历史问题的经验和数据,能够快速定位问题的根源,并直接为用户提供清晰的诊断结果,帮助团队从根本上解决业务问题,提升系统的稳定性和可靠性。

解决方案:用操作系统控制台诊断

进程热点持续追踪生成进程热点主要是下面三个步骤:
1. 栈回溯:获取内核态和用户态的详细调用栈信息,此时只是包含调用链及地址信息。

  1. 符号解析:将调用栈中的内核地址和用户态地址解析为用户易于理解的函数名称。
  2. 火焰图生成:通过火焰图的形式直观地展示调用栈数据。

图片
接下来,我们将深入探讨栈回溯和符号解析的策略,并详细阐述 SysOM 所采纳的具体方案。

方案介绍

栈回溯方案分析

栈回溯主要是获取当前程序的完整调用栈,它是生成火焰图的首要且关键的步骤,这一过程中存在两个主要的技术挑战:

  1. 无 fp(frame pointer,帧指针)的应用程序:为了优化性能,众多程序选择不保留fp。这导致我们无法依赖传统的基于fp回溯的方法来获取调用栈信息。因此,我们必须转而采用基于 dwarf 的更为复杂的栈回溯技术。
  2. Java、Python 等解释型语言的栈回溯:这些解释型或高级编程语言各自拥有独特的栈帧结构。因此,关键在于识别当前运行的程序,并准确解析出相应的栈帧信息。

为了应对这两个挑战,SysOM 利用 eBPF 的编程灵活性,支持无 fp 的应用以及解释型语言的栈回溯功能。除了 eBPF,其他主流的栈回溯方案包括 perf 和语言级别的接口(例如 Java 提供的 JVM TI)。以下是对这三种栈回溯方案的对比分析。
image.png

从上表中我们可以观察到不同方案各自的优势和局限性。

1)Perf 作为一个历史悠久的性能分析工具,它支持所有版本的内核,但在处理动态语言方面表现不足。此外,当使用基于 dwarf 的栈回溯时,由于需要将整个用户态栈空间输出到用户态程序,这会导致较大的资源消耗。

2)eBPF 的可编程性为新型栈回溯方案开辟了广阔的可能性,尤其是在支持动态语言栈回溯方面,通过分析代码运行时信息,能够完整解析出 Java、Python 等动态语言的调用栈,充分展现了 eBPF 的灵活性。唯一的限制是它对内核版本有一定的要求。

3)至于语言级别的采样工具,如 async-profiler,它们能够利用 JVM 提供的接口来收集栈信息,不依赖于内核版本,且资源消耗较低。然而,由于它们是进程级别的侵入式采样,存在极低概率导致业务应用崩溃,因此在稳定性方面存在不足。

对于 SysOM 而言,其设计目标是能在生产环境中持续稳定运行。因此,在确保功能完整性的基础上,稳定性被视为最重要的因素。为了实现这一目标,SysOM 集成了三种不同的方案,以便在各种场景下都能提供完善的功能支持。在底层的决策逻辑中,eBPF 被设定为最优先选项,其次是 perf,最后是语言级接口。下面的图表展示了根据不同编程语言和内核版本选择的栈回溯方案。

图片

符号解析方案分析

符号解析主要是将对应的地址转换成函数名,一般地,对于编译型语言的应用可以通过查找 elf 文件的符号表即可完成,对于解释型语言需要从进程内存中读取符号。这些是符号解析所需要解决的技术问题。从架构方案来看,存在两种方案选择:
image.png

从上表中可以观察到,本地符号解析依赖较少,由于需要进行符号缓存以加速查找速度,这会导致较大的内存占用。此外,由于大多数业务应用在生产环境中部署时不包含 debuginfo,可能会出现符号缺失,进而影响符号的准确性。相比之下,远程符号解析的部署依赖会多些,例如依赖网络传输调用栈信息,但它不需要在业务机器上缓存符号,因此内存占用较低。同时,远程解析可以从类似 yum 源的地方下载应用的 debuginfo 包,以获得更完整的符号信息。

本地解析更适合于单台机器的性能剖析,而远程解析更适合于集群和大规模部署,能够显著降低整体开销。例如,如果集群内部署的是同一版本的 MySQL 应用,那么只需建立一个全局的符号缓存,从而减少资源消耗。鉴于本地和远程符号解析各有优势,SysOM 同时支持这两种方案。

整体架构

下面的架构图是由底层组件 Coolbpf profiler 至前端的完整系统结构,它由三个主要部分组成:Sysom 前端、Sysom Agent 和 Coolbpf profiler,其中 SysOM 是智能运维平台,Coolbpf 是 eBPF 采集工具,SysOM Agent 负责启动 Coolbpf 功能及数据通信。
图片

下面是对每个部分的详细介绍:

1)SysOM 前端:这是用户与系统交互的界面,提供了性能分析的可视化功能。包含三个主要功能模块:

  • 热点分析:分析并展示程序中性能瓶颈的热点区域。
  • 热点对比:允许用户比较不同实例、不同时间点或不同条件下的性能热点变化。
  • CPU&GPU 热点图:提供 CPU 和 GPU 的性能热点图,帮助用户识别 GPU 性能问题。

2)SysOM Agent:作为中间层,SysOM Agent 负责收集和处理性能数据,并将结果发送到前端。包含四个热点模块:

  • OnCpu 热点:检测 CPU 上的热点问题。
  • OffCpu 热点:检测进程为什么被阻塞。
  • 内存热点:识别内存使用中的热点区域。
  • 锁热点:分析并报告锁竞争导致的性能问题。

3)Coolbpf profiler:这是底层的通用性能分析库,为 SysOM Agent 提供支持。包含两个主要部分:

  • eBPF&perf 栈回溯:①利用 eBPF 技术在内核态进行调用栈的捕获和分析,支持多种编程语言,如 C/C++/Rust/GoLang,以及 Java/Python/Luajit;②使用 perf 工具进行调用栈的捕获,这包括原生代码的符号解析和基于 perf 的 C/C++/Rust/GoLang 的调用栈分析。
  • 用户态符号解析:处理用户态程序的符号信息,包括编译型程序的符号表和解释型或高级语言运行时符号。

前端展示

本节将重点介绍热点分析和热点对比前端界面使用方法。

热点分析

热点分析的大致步骤如下:
1)参数选择:依次选择实例 ID、进程名、热点类型及时间范围。最后点击“执行热点追踪”按钮。需要注意的是热点类型是动态的,也就是会根据当前时间段该进程包含哪些热点类型来进行渲染,比如只包含 OnCpu,那么热点类型下拉列表就只有 OnCpu。
图片
2)OnCpu 热点:我们选择 OnCpu 后,就会立即渲染出如下图所示的 OnCpu 的火焰图。
图片
3)内存热点:我们选择“内存”后,就会立即渲染出如下图所示内存占用的火焰图。
图片

热点对比

热点对比对于分析正常环境和异常环境是一大杀器,能够精准的分析出差异,进而确定问题根因。使用步骤大致如下:1)参数选择:相比热点分析只需要选择一个机器实例,热点对比功能则需要两个机器实例,参数选择完毕后,点击“执行对比分析”按钮,则可触发生成对比火焰图。
图片

2)内存差分火焰图:下图是内存热力类型的差分火焰图,由于我们选择的机器实例、进程、时间段都是一致的,所以差分火焰图最后呈现都是灰色,表示不存在热点差异。
图片

案例分析

接下来将通过三个实际的案例来介绍下 SysOM 进程热点追踪如何快速地帮助我们定位线上问题。

案例一:load 高

load 高是线上经常遇到的问题类别,load 高问题也有很多类型。本案例重点介绍在定位因 sys 高导致的 load 高问题。最近,遇到了某客户出现每隔一段时间就会出现 load 飙高,比正常时间段内高十余倍。下面让我一起看看如何通过 SysOM 进程热点追踪快速定位该问题。

从下面的 CPU 热点分布图上,我们能够看到,在 CPU 热点图在 14:15 附近有突增,和 load 飙高的时间点基本吻合。

图片
缩小观察时间轴,选取 CPU 热点最高的时间段,我们看到以下的热点图。
图片

从热点火焰图上我们看到热点最高的是native_queued_spin_lock_slowpath 函数,初步判断这是等锁,是受害者第一现场,点击热点函数,火焰图中可以高亮显示。
图片
可以一看到,绝大多数进程都是在等锁。那么我们怎么从这些热点中找到锁的持有者呢?

我们先从火焰图上看看,大家在等什么锁,是否在等同一把锁?

通过点击火焰图热点块,可以放大某一个调用栈。
图片

通过分析 do_wait 函数,其内部会在等 tasklist_lock read 锁。
图片

通过分析 do_exit 函数,其内部也是在等 tasklist_lock write 锁。
图片

依葫芦画瓢,随机再找几个,发现大家都是在等 tasklist_lock 锁,有等 read 锁的,也有等 write 锁的。

接下来就是要看看,能否通过进程热点追踪快速找到锁的持有者了。

tasklist_lock 锁的设计是一把关中断才会去拿的 rw 锁,理论上讲是会被一个内核线程独占持有的,直到主动退出临界区,才会主动释放锁。基于这个原理,我们从火焰图上应该是能够找到一根柱子独占了这把锁。这里利用 liveTrace 提供的函数调用关系,我们逐个看下热点 top 函数的调用关系图。
图片

选择 top1,看到都是在等 tasklist_lock 锁的进程信息。
图片

选择 top2,是在做进程退出的函数,大部分是在做等 tasklist_lock 锁的热点上。
图片

选择 top3,通过分析 copy_process 函数,其会在等 tasklist_lock write 锁。
图片

选择 top4,这里看到 _cond_resched 主要是被 do_exit 和 copy_process 调用的。
图片

选择 top5,关键来了,我们期待的光秃秃的一根柱子终于出现了,结合内核的 tg_rt_schedulable 代码,我们知道该调用栈上是持有了 tasklist_lock read 锁的,也就是持有的所有关键调用栈被找到。

案例二:网络超时

某客户反馈业务网络偶发超时,通过查看进程热点追踪,发现热点在nft_do_chain。下图是热点追踪显示某个时刻网络超时时的函数表和火焰图。
图片

nft_do_chain 是处理 netfilter 规则的函数,很容易想到是 netfilter 规则过多导致网络协议栈处理速度变慢。通过 nft list ruleset 查看发现存在 12000+ 条规则。
图片

案例三:进程 CPU 占用高

某客户机器上面的 shell 脚本 CPU 占用高。下图展示了捕获的进程热点火焰图。通过火焰图,我们可以发现热点主要集中在 shell_execve,即在解析 Shell 脚本命令的过程中。因此,可以推测当前 Shell 脚本可能陷入了异常的死循环,这导致 Shell 解释器在解析和执行 Shell 命令时出现问题。因此,下一步需要定位当前 Shell 脚本中异常的命令。
图片

我们了解到,Shell 脚本是通过 execve 系统调用来执行 Shell 命令的,因此我们使用 strace 来跟踪 execve 的调用。从下面的结果图中可以看出,该脚本正在不断重复执行 ps 和 awk 命令。然后在shell脚本源码内搜索ps和awk,很轻松定位到问题源码。
图片

通过 SysOM 进程热点追踪,我们初步评估了 Shell 解释器的运行状态,判断其进入了死循环并重复执行某条异常命令。接着,通过 strace 命令定位到了异常的 Shell 命令,并返回到脚本源码中确认了问题代码的位置。

使用 OS 控制台的过程中,有任何疑问和建议,您可以搜索群号:94405014449 加入钉钉群反馈,欢迎大家扫码加入交流。

阿里云操作系统控制台PC端链接:https://alinux.console.aliyun.com/


龙蜥社区
40 声望13 粉丝

OpenAnolis龙蜥社区由国内外头部企业联合建立的操作系统开源社区。