SysOM Agent:3分钟定位CPU周期性抖动元凶

阿里云SysOM Agent三分钟定位CPU周期性抖动,通过火焰图等手段直击Negative Dentry堆积导致的VFS锁竞争,高效解决传统方法难以发现的系统问题。

原文标题:当 CPU 莫名抖动时,SysOM Agent 如何 3 分钟定位元凶?

原文作者:阿里云开发者

冷月清谈:

本文讲述了在生产环境中,CPU出现周期性飙升却找不到高CPU进程的案例。通过传统的排查方法难以定位问题,而阿里云SysOM Agent通过火焰图、调用栈等手段,快速定位到Negative Dentry堆积引发的VFS锁竞争风暴是导致CPU抖动的根本原因。文章详细介绍了SysOM Agent的工作原理和优势,以及如何使用SysOM Agent快速诊断和解决类似问题,将平均诊断时间从4小时缩短到5分钟。此外,还介绍了如何接入SysOM MCP,以及Negative Dentry的概念和自查方法。

怜星夜思:

1、文章中提到Negative Dentry堆积会导致CPU抖动,那么除了避免访问不存在的路径,还有没有其他方法可以缓解或预防这个问题?比如调整内核参数或者优化文件系统的配置?
2、SysOM Agent使用了火焰图定位问题,但火焰图对于不熟悉内核的人来说可能比较难以理解。有没有更直观的方式来呈现CPU使用情况,或者说有没有可视化的工具可以帮助理解火焰图?
3、文章提到SysOM MCP可以集成到各种AI Agent平台,让AI像专家一样诊断系统问题。那么,如果我想开发一个类似的AI Agent,需要具备哪些方面的知识和技能?

原文内容

一个真实的生产案例:CPU 周期性飙升,却找不到任何高 CPU 进程。

故事的开始:一个让人抓狂的 CPU 抖动问题

深夜 2 点,小王被监控告警惊醒。

公司核心业务服务器的 CPU 出现了诡异的"抖动"——每隔几秒就会飙到 80%,然后又落回 20%,如此反复。

%Cpu(s):  2.5 us, 45.0 sy,  0.0 ni, 52.5 id...  <- 突然飙升
%Cpu(s):  3.0 us, 12.0 sy,  0.0 ni, 85.0 id...  <- 又落回来
%Cpu(s):  2.0 us, 55.0 sy,  0.0 ni, 43.0 id...  <- 又飙了
奇怪的是:
  • top 看不到任何高 CPU 的进程。

  • sys 很高,但 user 很低。

  • 业务日志没有任何异常。

"到底是谁在搞鬼?" 小王盯着屏幕一脸茫然。

传统排查:大海捞针

按照常规思路,小王开始了漫长的排查:

# 看进程?没有异常
top -c

#
 看系统调用?太多了看不过来
strace -p xxx

#
 看内核日志?一切正常
dmesg

2 个小时过去了,问题依然没有头绪。
如果你也遇到过类似的场景,一定能理解那种"明明有问题却找不到原因"的抓狂感。

SysOM Agent 登场:3 分钟定位根因

第二天,小王决定试试 SysOM Agent。

阿里云操作系统控制台(https://alinux.console.aliyun.com是一站式操作系统运维管理平台,提供了内存、I/O、网络、内核崩溃等强大的系统诊断能力,SysOM是操作系统控制台的运维组件。SysOM Agent 是SysOM 的智能助手,接入了 SysOM MCP 的诊断能力。点击右上角的图标即可和 SysOM Agent 对话。

小王只输入了一句话:

“我的实例 i-12345 的 CPU 使用率出现周期性抖动,sys 很高”

接下来发生的事情,让他大开眼界——

第一步:火焰图锁定热点函数

SysOM Agent 自动调用了 CPU Profiling 能力,采集了抖动时间段的火焰图。

结果一目了然:

native_queued_spin_lock_slowpath   <- 占用 40%+ CPU!
  _raw_spin_lock
    lockref_get_not_dead
      legitimize_path
        try_to_unlazy_next
          walk_component
            lookup_fast

Agent 诊断结论:大量 CPU 时间消耗在 native_queued_spin_lock_slowpath  ——这是内核自旋锁的慢路径。

第二步:追溯问题源头

Agent 进一步分析调用栈:

lookup_fast → try_to_unlazy_next → __legitimize_path

这条链路说明:VFS 路径解析时,RCU 快路径失败,被迫走到了需要获取锁的慢路径。

但为什么会这样?

第三步:抓到“真凶”

Agent 进一步分析调用栈:Agent通过火焰图深入分析,确认 CPU 抖动的根因为 Negative Dentry 堆积引发的 VFS 锁竞争风暴。

  • 诱因: 业务逻辑中存在高频访问不存在文件的行为,导致内核 Dentry Cache 中堆积了海量的 Negative Dentry。
  • 触发: 当系统触发内存回收或 Dentry 缓存达到阈值时,内核回收进程会调用 shrink_dentry_list 尝试销毁这些条目,这会频繁修改父目录的序列计数器(d_seq)并持有 dentry 的自旋锁(d_lock)。
  • 冲突: 此时,业务进程的高频路径解析(RCU Path Walk)会因为检测到 dentry 状态变更或序列号不一致而导致 RCU 模式失效。
  • 恶化: 大量并发线程被迫从 RCU 模式切换到 Refcount 模式(Unlazy 流程),并集体尝试调用 legitimize_path 来获取 dentry 的引用。该过程需要频繁竞争 d_lock 自旋锁,最终在 lockref_get_not_dead 处爆发严重的锁竞争。
  • 现象: 这种高密度的锁竞争将 CPU 拖入 native_queued_spin_lock_slowpath 的长时自旋中,表现为系统负载和内核态 CPU 使用率的剧烈抖动。
完整诊断报告详见文末的附录1。

Negative dentry 导致的 CPU 抖动是一个非常隐蔽的问题:

特征
说明
难发现

top/ps 看不到高 CPU 进程

难定位

需要火焰图 + 内核知识

易忽视

抖动可能被误认为"正常波动"

影响大

会导致业务响应延迟不稳定


SysOM Agent 已经帮助多家企业定位过类似问题,平均诊断时间从 4 小时缩短到 5 分钟。

为什么 SySOM Agent 能做到?

1、多维度数据融合

不是简单地看 top/vmstat,而是:

  • 火焰图:精准定位内核热点。
  • 调用栈:理解代码执行路径。
  • bpftrace:动态追踪内核行为。

2、专家级诊断逻辑

Agent 内置了资深 SRE 的诊断思路:

  • 看到 native_queued_spin_lock_slowpath   → 联想到锁竞争。

  • 看到 lookup_fast 降级 → 理解 VFS 缓存机制。

  • 看到 dentry 相关 → 检查文件系统访问模式。

3、一句话交互

不需要你记住复杂的命令,只需描述问题现象:

❌ 传统方式: perf record -ag -- sleep 20 && perf report && bpftrace ...
✅ SysOM Agent: "我的机器CPU sys 很高,有周期性抖动"


立即体验 SysOM Agent

如果你的系统也有类似的 CPU 抖动问题,不妨让 SysOM Agent 试试,让专家级诊断能力触手可及:

1、登录 SysOM 控制台(https://alinux.console.aliyun.com),纳管节点,等待问题复现。

2、打开智能助手,输入问题描述,自动诊断结果。

相关文档

如何纳管节点:https://help.aliyun.com/zh/alinux/component-management

进程热点追踪:https://help.aliyun.com/zh/alinux/process-hotspot-tracking

如果你有自己的 Agent,也可以试试接入SysOM MCP(https://github.com/alibaba/sysom_mcp),SysOM MCP 脱胎于阿里云操作系统控制台,把复杂的运维操作转化为 AI 可直接调用的标准工具,让 AI Agent 能像专业工程师一样“动手”诊断系统问题——用户无需懂命令,只需用自然语言提问,即可获得精准的系统级分析。

SysOM MCP 支持 --stdio (本地嵌入)和 --sse (HTTP 服务)两种模式,轻松集成各类 AI 客户端。

要在支持 MCP 协议的 AI Agent 平台(如 Qwen Code)中使用 SysOM MCP,首先需将项目代码克隆到本地:
git clone https://github.com/alibaba/sysom_mcp.git
cd sysom_mcp
再在配置文件中添加如下配置,就可以让 AI 助手能以自然语言驱动操作系统及运维操作。
{
  "mcpServers": {
    "sysom_mcp": {
      "command""uv",
      "args": ["run""python""sysom_main_mcp.py""--stdio"],
      "env": {
        "ACCESS_KEY_ID""your_access_key_id",
        "ACCESS_KEY_SECRET""your_access_key_secret",
        "DASHSCOPE_API_KEY""your_dashscope_api_key"
      },
      "cwd""<sysom mcp项目目录>",
      "timeout"30000,
      "trust": false
    }
  }
}

附录1:完整诊断报告
┌─────────────────────────────────────────────────────────┐
│  SysOM Agent 诊断报告                                    │
├─────────────────────────────────────────────────────────┤
│  问题现象: CPU sys 周期性飙升,load 抖动                 │
│                                                         │
│  根因分析:                                               │
│  1. 用户进程高频访问不存在的路径                 │
│  2. 产生大量 negative dentry 并被周期性回收              │
│  3. VFS 路径解析从 RCU-walk 降级到 REF-walk              │
│  4. dentry 自旋锁竞争导致 CPU 抖动                       │
│                                                         │
│  解决方案:                                               │
│  1. 应急: sync && echo 2 > /proc/sys/vm/drop_caches    │
│  2. 修复: 检查业务代码,避免访问不存在的路径             │
│  3. 优化: 缓存文件存在性检查结果                         │
└─────────────────────────────────────────────────────────┘

附录2:什么是 Negative Dentry?

当你访问一个不存在的文件时:
ls /path/to/nonexistent_file
# ls: cannot access '/path/to/nonexistent_file': No such file or directory
内核不会每次都去磁盘查找,而是会创建一个 negative dentry 来缓存"这个文件不存在"的信息。
这本来是一个优化机制,但当:
  • 大量进程高频访问不存在的路径
  • 同时系统又在回收 dentry 缓存
就会触发 VFS 层面的锁竞争,导致 CPU 抖动。
如何自查?
# 查看 dentry 缓存状态
cat /proc/sys/fs/dentry-state
# 输出: nr_dentry nr_unused age_limit want_pages dummy dummy
# 如果 nr_dentry 数值很大(数十万以上),可能存在问题

SysOM Agent —— 让复杂问题变简单

 联系我们 

若想使用更全面的 SysOM 功能,请登录阿里云操作系统控制台体验,地址(复制链接至浏览器打开或文末点击阅读原文)

https://alinux.console.aliyun.com/

您在使用操作系统控制台的过程中,有任何疑问和建议,可以搜索钉群号94405014449 入钉钉群反馈。

想手动生成火焰图,其实也不难,就是稍微麻烦点。首先你需要使用 perf 工具来收集 CPU 的 profile 数据,例如:

bash<br>sudo perf record -F 99 -p <pid> -g -- sleep 30<br>sudo perf script > out.perf<br>

其中 <pid> 是你要分析的进程 ID。然后,你需要使用火焰图工具(比如 Brendan Gregg 的 FlameGraph)来将 out.perf 文件转换为火焰图:

bash<br>./stackcollapse.pl out.perf > out.folded<br>./flamegraph.pl out.folded > flamegraph.svg<br>

这样你就可以得到一个 flamegraph.svg 文件,用浏览器打开就可以看到火焰图了。当然,前提是你得先安装 perf 和 FlameGraph 工具。

手动生成火焰图的确需要一些准备工作,以下是一个更详细的步骤:

1. 安装 perf: sudo apt-get install linux-tools-common linux-tools-$(uname -r) linux-perf (Debian/Ubuntu)
2. 收集数据:
* perf record -F 99 -p <pid> -g -- sleep 30 (针对特定进程)
* perf record -F 99 -ag -- sleep 30 (系统级别,所有进程,可能产生大量数据)
3. 转换数据:
* perf script > out.perf
4. 安装 FlameGraph:
* git clone https://github.com/brendangregg/FlameGraph.git
* 将 FlameGraph 工具目录添加到 PATH 环境变量
5. 生成火焰图:
* ./stackcollapse-perf.pl out.perf > out.folded
* ./flamegraph.pl out.folded > flamegraph.svg

此外,还可以考虑使用 bpftrace 这样的动态追踪工具,它可以更灵活地收集数据,并生成火焰图。但 bpftrace 的学习曲线可能会更陡峭一些,根据你的需要在 perfbpftrace 之间进行选择。

我觉得吧,最有效的学习方法就是“拜师”!找个经验丰富的运维大佬,跟着他学习,耳濡目染,进步肯定飞快!:rocket:

当然,如果找不到大佬,也可以自己创造机会。比如,主动承担一些复杂的运维任务,遇到问题就积极请教别人,或者参与一些POC项目,在实践中学习和成长。

另外,还可以关注一些技术大牛的博客和公众号,学习他们的经验和技巧。比如,Brendan Gregg 的博客(http://www.brendangregg.com/)就有很多关于性能分析和火焰图的文章,非常值得学习。

谢邀,怒答一波!我觉得啊,与其想方设法去缓解 Negative Dentry 堆积,不如从根本上解决问题,直接让程序猿把 bug 改了!:dog_face:

当然,如果实在改不了,或者需要临时缓解一下,可以考虑用个定时任务,定期清理一下 dentry 缓存,虽然有点暴力,但总比 CPU 抖动好!

echo 2 > /proc/sys/vm/drop_caches # risky,慎用!!!

赞同楼上的说法!另外,建立知识体系也很重要。SysOM Agent 内置了资深 SRE 的诊断思路,这意味着我们需要不断学习和积累经验,才能对各种系统问题有更深入的理解。例如,看到 native_queued_spin_lock_slowpath 就要能联想到锁竞争,看到 dentry 相关就要想到文件系统访问模式等等。

这个问题问得好!除了文中提到的情况,以下几种场景也可能导致 Negative Dentry 大量堆积:

1. 程序 Bug: 某些程序逻辑可能存在缺陷,导致频繁尝试访问不存在的文件或目录。
2. 配置错误: 错误的配置可能导致程序尝试读取不存在的配置文件或数据文件。
3. 恶意攻击: 恶意攻击者可能会发起大量针对不存在文件的请求,试图耗尽服务器资源。

针对这些情况,我们需要从代码层面、配置层面和安全层面进行排查和优化。

别看这个命令好像很厉害的样子,其实就相当于给电脑重启了一下。重启能解决很多问题,但重启也意味着服务中断,而且治标不治本。所以,这个应急方案只能是万不得已的时候用一下,用完之后赶紧去查代码,看看为什么会产生这么多Negative Dentry,不然下次还会抖!

从学术的角度分析,该命令的副作用不容忽视。drop_caches 通过直接干预内核的内存管理机制来释放缓存,这可能会对依赖缓存的应用程序产生负面影响。例如,数据库系统通常会利用 page cache 来加速查询,清空缓存会导致大量物理 I/O,从而降低数据库的性能。此外,频繁使用 drop_caches 可能会掩盖潜在的内存泄漏问题或文件系统访问模式低效等问题,不利于长期的系统稳定性。

因此,在生产环境中,除非确信该操作不会对关键业务造成严重影响,否则应谨慎使用 drop_caches,并结合其他诊断工具 (如 vmstat, iostat) 来评估其影响。

火焰图是一种非常直观的可视化工具,用于分析CPU的使用情况。它能告诉你CPU时间都花在了哪些函数上。这里简单说一下火焰图的解读方法:

* X轴: 表示时间,或者说是样本的数量。一个函数的块越宽,表示CPU在这个函数上花费的时间越多。
* Y轴: 表示调用栈的深度。从下往上看,每一层都是上一层的调用者。最顶层的函数就是当前CPU正在执行的函数。
* 颜色: 通常是随机的,没有特殊含义,主要是为了区分不同的函数块。

解读技巧:

1. 找“火焰”顶端最宽的块: 这些块代表CPU时间占比最高的函数,通常是性能瓶颈所在。
2. 沿着调用栈向上看: 看看这个热点函数是被哪些函数调用的,有助于理解问题的上下文。
3. 注意“锯齿状”的边缘: 如果火焰图的边缘很平滑,说明CPU一直花在同一个函数上;如果边缘有很多锯齿,说明CPU在不同的函数之间频繁切换,可能存在锁竞争或上下文切换的问题。

这个命令实际上是在清理Linux内核的page cache、inode和dentry cache。sync命令确保所有dirty buffers都被写入磁盘,防止数据丢失。echo 2 > /proc/sys/vm/drop_caches则是通知内核释放page cache(对应数字1)、dentries和inodes(对应数字2)、以及slab cache(对应数字3)。但需要注意的是,清空缓存会暂时降低系统性能,因为后续的读操作可能需要直接从磁盘读取数据,直到缓存重新建立起来。在生产环境中需要谨慎使用,尤其是在I/O压力大的系统上。

从更学术的角度来说,这个操作会影响系统的cache hit ratio. 原本命中cache的IO操作,现在需要直接访问磁盘,latency会显著增大,同时磁盘IOPS也会升高。虽然能缓解dentry导致的CPU问题,但实际上是将压力转移到了IO子系统。所以,这是一个trade-off。

从操作系统的角度,如果文件系统的缓存策略不合理,或者内存压力过大,导致dentry缓存频繁被清理和重建,也会间接导致negative dentry的累积效应放大。

这个命令实际上是手动触发Linux内核的缓存清理机制。sync命令确保所有文件系统缓存都被写入磁盘,echo 2 > /proc/sys/vm/drop_caches会释放pagecache、dentry和inode。这样做可以缓解dentry堆积,但也会导致短时间内IO负载升高,因为后续的文件访问会直接读取磁盘。

不依赖工具的话,比较困难。但如果经常遇到类似问题,可以尝试通过观察系统指标初步判断。例如,如果%sys很高,但%user很低,且系统load average也很高,同时iowait不高,可以初步怀疑是内核态的锁竞争导致的。更进一步,可以查看/proc/interrupts,看看是否有大量的中断被某个CPU核心处理,这可能暗示着锁竞争集中在那个核心上。当然,这些都只是初步判断,最终还是要借助工具。

楼上说的是一种可能,我补充一点,还有权限问题。如果程序尝试访问大量它没有权限访问的文件,也会产生大量的 negative dentry。所以除了检查代码中的文件路径,还要检查程序的权限配置,看看是不是有不该访问的文件被访问了。

我觉得还可以从监控入手。 完善的监控体系可以在问题发生前就发出预警。 比如,可以监控CPU使用率、磁盘I/O、网络流量等关键指标。 当某个指标出现异常波动时, 可以及时介入排查, 防患于未然。 另外, 定期进行性能测试和压力测试, 也可以帮助我们发现潜在的性能问题。

我想到一个比较极端的情况,恶意攻击!如果有人故意构造大量不存在的文件路径,然后让服务器去访问,是不是就可以利用这个漏洞搞DDoS攻击了? 这样会不会消耗大量服务器资源? 所以除了业务层面的问题,安全性也需要考虑。

火焰图算是神器了,直观展示 CPU 消耗在哪些函数上。不过我个人更喜欢用 perf,功能强大,可以采样各种事件,生成报告。缺点是上手难度略高,需要一定的内核知识。

从学术角度来看,CPU 的 sys 使用率高,通常意味着内核花费了大量时间在执行系统调用、处理中断、管理内存等方面。这可能反映了应用程序与操作系统内核之间的交互过于频繁,或者内核本身的效率存在瓶颈。深入分析内核行为,例如通过 perf 工具或 SystemTap 脚本,有助于识别性能瓶颈。