新闻详情

新闻详情

首页 / 资讯中心 / 详情

IO tracing实战:从系统调用到块设备层的性能排查指南

发布时间:2026/9/29 15:28:38来源:尧图网络
IO tracing实战:从系统调用到块设备层的性能排查指南
做后端和运维这些年IO问题一直是最容易让人抓狂的。CPU飙高、内存不足都有比较明确的排查路径唯独IO出问题的时候机器看着一切正常CPU不高、内存够用、磁盘空间也还有但业务延迟就是下不来。遇到这种案子就得请出io tracing那套家伙事儿了。所谓io tracing简单说就是沿着输入输出请求走过的路径把每个环节的耗时、队列、完成情况全部记录下来从“黑盒”变成“白盒”。这篇文章我想把平时自己真正在用的IO tracing常用工具梳理一遍从原理讲到实操再附上排查案例和踩坑记录希望对后端开发、SRE、存储运维的朋友有实际帮助。1. 为什么要做IO tracing先搞懂底层逻辑1.1 一条IO请求到底经历了什么我们经常说“磁盘慢”“IO有瓶颈”但慢在哪里、瓶颈在哪一层很多人其实是含糊的。一个写请求从应用程序发出到真正落到硬盘上会经过大致这么几步应用发起系统调用write、fsync这类→ 虚拟文件系统 VFS 层 → 具体文件系统ext4、xfs、btrfs等→ 页缓存page cache→ 块设备层block layer对应 bio、I/O 调度器、请求队列→ 设备驱动 → 物理设备机械盘、固态盘或NVMe。这几层里任何一个环节拥堵表现都可能一样就是“写不进去、延迟变高”。但处理方式完全不同如果是页缓存导致的问题可能要调脏页回写参数如果是调度器或队列积压要改队列深度或调度算法如果是设备本身老化那就得换盘。很多人上来就盯 %util 和 iowait这是最容易误判的地方。iowait 只是表明CPU有线程在等IO完成不代表磁盘就是瓶颈。想要真正定位就必须分层观测io tracing 干的就是这个活。拿生活里的快递配送打比方你只知道包裹晚了两天不能直接骂快递员得看是仓库分拣慢了、运输途中堵了还是派送网点爆仓了。每一层都可能花时间你得在每个中转环节打点计时。1.2 观测层级决定工具选型理解了路径就能理解为什么工具这么多、又为什么不能一个工具打天下。系统级指标工具iostat、pidstat、sar告诉你“整体有多忙、耗时多长”事件级追踪工具strace、perf trace告诉你“应用发了哪些系统调用、每次花了多久”块层工具blktrace、blkparse、bcc里的biosnoop告诉你“进入磁盘队列的IO长什么样、什么时候完成”动态追踪工具bpftrace、BCC则能灵活地在任意内核函数上挂探针想统计哪个环节就统计哪个环节。一个需要提前说明的重要概念是“观测者效应”。IO tracing 本身有开销在高并发的生产环境里挂上 strace 甚至可能让进程慢上几倍。这不是工具不好用而是所有动态插桩工具的通病。所以实际排查时我的经验是先用轻量级的聚合统计工具划定大方向再用重量级的详细追踪工具精确缩小范围不要一上来就把全家桶全挂上。2. 工具全景先用一张表理清IO tracing全家桶2.1 系统级指标监控工具怎么选系统级工具解决的是“有没有问题、问题在哪个维度”的阶段。我最常用的三个iostat 是最基础的-x 参数能看到扩展统计r/s、w/s每秒读写次数、rkB/s、wkB/s吞吐、awaitIO请求平均耗时、svctm平均服务时间、avgqu-sz平均队列长度、%util设备利用率。注意这些指标在机械盘时代很有参考性到了 SSD/NVMe 时代%util 经常是超过100%的因为它按机械盘的单队列模型计算很多情况下不能直接当作饱和度判断。pidstat -d 能按进程粒度数IO直接告诉我们哪个进程在疯狂读写。iotop 则像 top 一样实时显示各进程的IO带宽和使用率排查“谁在拖慢系统”很直观。sar 一般配合历史数据使用看看问题是偶发还是一直存在这个对压测和线上复盘都很有用。2.2 事件级追踪工具的分类逻辑系统级指标只能说明“有问题”说明不了“为什么”这时候要上事件级工具。它们大体分两类。一类是系统调用追踪代表是 strace 和 perf trace。strace 能记录进程发起的每个系统调用、参数和返回值配合 -T 还能打印每个系统调用耗时。perf trace 是它的低开销替代品语义差不多但基于 perf 子系统采样开销更小。第二类是内核块设备层追踪代表是 blktrace blkparse、btt它们直接在内核的块设备层插入探针记录 IO 请求从入队queue到下发issue再到完成complete的完整生命周期。再往后就是现代动态追踪的代表 BPF 系列bpftrace 支持单行脚本快速统计BCC 则提供了一堆现成工具比如 biolatency、biosnoop、filetop、cachestat覆盖范围从文件系统到块设备层。另外提一句如果你接触 Android 平台的应用或系统级性能分析会看到 systrace、perfetto 这类工具Linux 上的这套 tracing 方法论在原理上完全可以平移过去但具体命令和内核接口略有差异通用场景下我们还是聚焦 Linux 生态来聊。3. 核心工具实操从strace到bpftrace3.1 strace系统调用级的快速排查先说 strace它是很多后端工程师排查IO问题的第一站。典型场景是某个服务进程写入延迟很高怀疑是系统调用层面有问题或者怀疑应用在疯狂调用 fsync。我的标准操作是这样的# 先看这个进程大概在哪些系统调用上耗时最久 strace -f -c -p 1234 # 然后针对可疑的系统调用做详细跟踪 strace -f -tt -T -e traceopenat,read,write,fsync,fdatasync,close,pread64,pwrite64 \ -p 1234 -o /tmp/trace.out参数含义拆解一下-f 表示跟踪子进程和子线程线程池模型的服务必须有-tt 输出微秒级时间戳用于分析时间线-T 打印每个系统调用耗时-e trace 做系统调用过滤一定要过滤否则输出量巨大而且会对性能造成严重影响-o 把结果写到文件不要直接刷到终端。拿到 trace 文件后怎么看我一般重点看两类东西。第一类是耗时异常大的系统调用比如一个 pwrite64 花了500毫秒那基本锁定IO路径有问题。第二类是 fsync/fdatasync 的调用频率和耗时如果应用每写一条小数据就调一次 fsync磁盘会疲于奔命这种模式对机械盘尤其致命会导致明显的写放大和延迟飙升。提示生产环境慎用 strace。我实测过在高并发IO密集的服务上挂 strace吞吐可能下降30%以上严重时直接引发雪崩。稳妥的做法是先用 strace -c 做几十秒的统计确有必要再用过滤条件挂详细跟踪而且尽量选低峰期。3.2 blktraceblkparse块设备层的“黑匣子”strace 看到的是应用视角但到了内核块设备层之后发生了什么它是看不到的。这时候用 blktrace 这一套它们可以在设备层完整记录每个 IO 请求从进入到完成的所有事件。先看基本流程# 捕获 /dev/sdb 上的块层事件持续30秒 blktrace -d /dev/sdb -o trace -w 30 # 解析结果 blkparse -i trace.blktrace.0 -o parse.out # 用 btt 做时间分析得到各阶段延迟统计 btt -i trace.blktrace.0blktrace 记录的事件里有几个关键时间点Q请求入队、I请求被调度器插入队列、D请求下发给驱动、C请求完成。btt 工具会基于这些事件计算出一组非常有价值的延迟指标Q2Q 表示相邻请求入队间隔对应IO并发度和压力Q2C 是从入队到完成的总延迟就是应用感知的排队服务时间D2C 是从下发给驱动到完成的时间基本就是设备真实服务时间。所以一个很重要的判断逻辑就出来了拿 Q2C 和 D2C 对比。如果 Q2C 高但 D2C 不高说明卡在队列和调度环节请求在排队如果 D2C 本身很高那就是设备的问题盘老了、坏了、或者接口带宽不够。有一次我帮同事排查数据库备份期间延迟飙升就是用这个办法定位到备份进程发出的请求太多把设备队列堵满了而不是磁盘本身故障。blktrace 有个需要注意的坑它采集的数据量非常凶猛一个繁忙的设备上跑几十秒可能产生几个GB的原始trace数据而且本身也会给块层带来额外开销。所以第一用小写 -w 窗口限制时间第二有条件的话用 -a mask 只开启必要的事件类型比如只追踪下发和完成事件可以加 -a issue -a complete第三解析时用 blkparse -O 丢弃没有实际IO事件的空闲块能大幅缩小输出。3.3 bpftrace/BCC动态追踪的现代打法如果说 blktrace 是块层的专用设备那 BPF 系列工具就是通用探测平台几乎可以在内核任何函数上做插桩灵活度非常高。这里先说安装。在 Ubuntu 24.04 或更新的 26.04 上安装很方便# bpftrace apt install bpftrace # BCC工具注意Ubuntu上包名和可执行文件名都带bpfcc后缀 apt install bpfcc-tools执行的时候工具名是 biolatency-bpfcc、biosnoop-bpfcc 这样的形式别直接敲 biolatency我第一次用的时候光这名字就纠结了一阵。内核要求方面5.x 以上内核基本都能正常用前提是内核编译时打开了 BPF 相关配置尤其是 CONFIG_DEBUG_INFO_BTF这个在较新的发行版上默认开启。老内核会报错升级内核或重新编译即可。最常用的场景是看IO延迟分布。block层延迟直方图# 打印块设备IO延迟直方图 biolatency-bpfcc或者更进一步直接看每次IO请求的事件明细# 实时打印块设备层IO请求-b表示显示块设备号 biosnoop-bpfcc -bbiosnoop 输出的内容相当于 blktrace 的精华版进程名、PID、设备、扇区、大小以及请求从下发到完成的时间。排查“哪个进程、在什么时间、对哪块磁盘发起了多大的请求、花了多久”这一条命令全包了。如果我需要一个完全自定义的统计逻辑那就上 bpftrace比如统计 vfs_read 的耗时分布bpftrace -e kprobe:vfs_read { start[tid] nsecs; } \ kretprobe:vfs_read /start[tid]/ { us[comm] hist((nsecs - start[tid]) / 1000); \ delete(start[tid]); }这一行脚本的意思很直白在 vfs_read 进入时记录时间返回时计算耗时按进程名分组输出直方图。BPF系列工具的生产安全性远比 strace 高它能做到内核级插桩但几乎不影响业务路径开销以微秒计这也是为什么我现在首选的详细追踪工具逐渐从 strace 迁移到 bpftrace/BCC 的原因。4. 一个真实案例从延迟突增到IO队列积压4.1 现象与第一轮排查去年遇到一个典型的IO问题某服务对外承诺P99延迟5ms结果压测时P99飙到50ms而且CPU、内存都看不出明显异样。磁盘用的NVMe型号不差直觉不应该是硬件问题。我先按前面的思路走。第一步iostat 看整体iostat -x 1 /dev/nvme0n1观察几轮发现%util 在80%上下波动但要知道NVMe是多队列设备%util在这种设备上意义有限真正刺眼的是 await 从平时的0.5ms涨到15msavgqu-sz 长期在几十左右理论上NVMe的队列深度很大但几十的常驻队列也说明请求堆积严重了。第二步定位进程用 iotop 和 pidstat 双管齐下pidstat -d 1 | sort -k 5 -rn | head很快就锁定了服务里某个线程组在持续大量写入单线程每秒写入次数非常高。这时其实已经有怀疑方向要么是应用写太频繁要么是内核层回写出了问题。4.2 用延迟直方图定位问题阶段到了这个时候我不急着上 blktrace先用更轻量的 BCC 工具看延迟分布把“慢在哪一层”先分开。biolatency-bpfcc -m # -m表示用毫秒单位输出显示IO请求延迟大多数落在10-20ms区间而且这个延迟是设备完成时间。这说明问题在块设备层及以下而不是应用系统调用层。接着我用 blktrace 抓了30秒数据btt 分析之后发现D2C设备服务时间平均只有1ms左右但 Q2C排队服务高达14ms。问题就清晰了设备本身很快请求在队列里等的时间太长这就是典型的队列积压不是硬件故障。为什么队列会积压再看一层通过 blkparse 的输出统计请求大小和到达模式。发现业务线程特别喜欢发4KB的小随机写而且一个请求完成之前不会发下一个这就导致每次IO都在等待队列里堆积的小请求慢慢被调度。多个线程叠加起来队列深度被塞满延迟自然高。4.3 修复与验证修复方向有两个一是应用层合并写入把零散的4KB小写攒成64KB甚至更大的批量写二是修改IO调度器NVMe 场景下默认用 none尽量别抱太大希望于调度合并重点在应用层和文件系统层做归一。另外我们当时还顺手调整了文件系统挂载参数在能够容忍掉电风险的前提下减少一次 fsync 的强制落盘次数。调整后我再用 biolatency 复查P99 从50ms降回6ms左右Q2C 恢复正常。整个过程里没有任何一块硬件故障纯粹是请求模式把队列堵死了。这个案例也印证了一个观点只看 iostat 的 %util 会得出“磁盘很忙”的假象而分层 tracing 能直接告诉你忙在哪里。5. 常见问题、踩坑记录与速查表5.1 这些坑我基本都踩过先说 strace 的坑。attach 到一个已经高负载的进程大概率会让它雪上加霜。我有一次在生产环境用 strace 跟一个写入密集型服务没加过滤条件结果服务延迟从20ms直接飙到200ms吓得赶紧摘掉。后面学乖了优先用 strace -c 做统计或者干脆用 bpftrace 做内核级采样只在必要时才做完整跟踪。再说 blktrace 的输出爆炸。刚开始我用 blktrace 整盘采集睡了半小时回来发现磁盘被trace文件写满了系统直接告警。这个工具产生的原始数据是真的大一定要用 -w 限制采集窗口并且早一点用 blkparse -O 做数据清理有条件直接在低峰期跑。BPF 系列工具最常见的坑是内核配置不满足。我遇到过在 CentOS 7 老内核上编译 BCC 各种报错后来统一换到新发行版才好。如果你用的还是老内核先查一下这几个东西# 查看 BTF 是否可用 ls /sys/kernel/btf/vmlinux # 查看内核是否开启 kprobe cat /proc/sys/kernel/kptr_restrict还有一个小细节不同内核版本的 tracefs 挂载点不同有的在 /sys/kernel/tracing有的在 /sys/kernel/debug/tracing使用 ftrace 方式手动开事件时先确认挂载状态。5.2 工具速查表我把日常排查中最常用到的命令整理成了一个表适合贴在终端旁边参照。场景推荐工具命令示例看整体IO负载iostatiostat -x 1看进程IO排行pidstat / iotoppidstat -d 1iotop -o看系统调用耗时stracestrace -f -tt -T -e tracefsync,write -p PID看块层请求生命周期blktrace blkparseblktrace -d /dev/sdb -w 30blkparse -i trace.blktrace.0看块层延迟直方图biolatency-bpfccbiolatency-bpfcc -m看单次IO事件明细biosnoop-bpfccbiosnoop-bpfcc -b看文件层热点filetop-bpfccfiletop-bpfcc看页缓存命中情况cachestat-bpfcccachestat-bpfcc自定义内核级统计bpftracebpftrace -e kprobe:vfs_read {...}5.3 排查思路建议最后给一个我常用的排查执行顺序不是说每次都要全套走完而是从轻到重、从粗到细先用 iostat/pidstat 判断系统整体状况和可疑进程然后用 iotop 或 pidstat -d 锁定进程判断问题在应用层还是内核层这一步可以用 strace -c统计模式或 biolatency 快速划分如果确认块层有问题上 blktrace btt 分析 Q2C 和 D2C判断是队列问题还是设备问题最后根据结论调应用模式、参数或换硬件并且用同样的工具复测验证。这个流程我有很长一段时间都在用实际解决问题效率很高。我个人在实际操作中的体会是io tracing 工具再多核心还是要养成“分层定位”的习惯。不要被单点指标带节奏iostat 的 %util 高不代表磁盘坏了strace 显示的 write 慢也可能是下游队列堵了只有一层层剥开找到真正消费时间的环节修复才有效。另外工具不在多把 strace、blktrace、BCC 这三类吃透足够覆盖日常绝大多数IO疑难杂症。建议找一个压测环境人为制造一些IO异常比如调低队列深度、故意发起大量4KB随机写然后用这套方法走一遍你会对这些工具的理解上一个台阶。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

【Cursor实战】零代码开发一个Dify工作流:用TaoToken统一Key打通DSL配置 2026/9/29 21:00:53

【Cursor实战】零代码开发一个Dify工作流:用TaoToken统一Key打通DSL配置

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
会议纪要软件到底怎么选?实测5款主流工具,帮你彻底告别加班整理笔记 2026/9/29 21:00:53

会议纪要软件到底怎么选?实测5款主流工具,帮你彻底告别加班整理笔记

你有没有过这样的经历:开了一整天的会,脑子已经转不动了,回到工位还得对着录音文件一点点听、一句句敲纪要?或者明明开会时觉得都记下了,回头一看笔记,全是零散的词,根本拼不出逻辑链条&#xf…

阅读更多 →
IAP升级后中断死机?VTOR重映射时机是关键 2026/9/29 21:00:53

IAP升级后中断死机?VTOR重映射时机是关键

1. 项目概述:为什么IAP升级后单片机一进中断就死机?真相藏在VTOR寄存器里你有没有遇到过这种场景:IAP固件升级程序写得严丝合缝,擦写校验全通过,跳转到新APP也顺利执行,但只要外部按键一按、串口数据一来、…

阅读更多 →
STM32上电启动全链路解析:从复位向量到第一个任务 2026/9/29 21:00:53

STM32上电启动全链路解析:从复位向量到第一个任务

1. 上电那一刻,芯片到底在干什么很多人调 STM32 调了几年,写业务逻辑、配外设、跑 RTOS 都不在话下,但一旦遇到“程序跑不起来”“HardFault 一上电就挂”“跳转 bootloader 后卡死”这类问题,就开始抓瞎。根子往往不在业务代码&a…

阅读更多 →
嵌入式开发中的Vibe Coding:AI编程效率与硬件确定性的平衡实践 2026/9/29 21:00:52

嵌入式开发中的Vibe Coding:AI编程效率与硬件确定性的平衡实践

1. 当“感觉流”编程撞上寄存器:一场关于效率与掌控的拉锯战“Vibe Coding”这个词最近在圈子里出现的频率越来越高,大概意思就是借助强大的AI编程助手,你只需要描述意图、把握方向、感受代码的“氛围”,具体的语法、API调用甚至模…

阅读更多 →
STM32从复位向量到uC/OS-II第一个任务:启动流程与PendSV上下文切换全解析 2026/9/29 21:00:46

STM32从复位向量到uC/OS-II第一个任务:启动流程与PendSV上下文切换全解析

1. 上电那一刻,芯片到底在干什么很多人第一次接触 STM32,都是从点灯开始的。写几行代码,编译下载,LED 亮了,任务完成。但如果我问你:从上电到main函数的第一行代码执行,中间到底发生了什么&…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉