简介:磁盘被打满到底是真实的业务需求量上来了呢?还是有什么野进程在占用 IO? iofsstat 帮你精准定位。

编者按sysAK(system analyse kit),是龙蜥社区系统运维 SIG 下面的一个开源项目,聚集阿里百万服务器的多年运维经验,针对不同的运维需求提供了一系列工具,形成统一的产品进行服务。本文总结了实际工作中 IO 打满、IO util 高问题的处理经验,将它梳理成一套理论分析方法并形成 iofsstat 工具,集成到了sysAK 工具集里。以下将由作者带大家一道领略 iofsstat 的独特魅力。

文/李光水:系统运维SIG核心成员、 毛文安:系统运维SIG负责人。

一、 需求背景

经常碰到这样一类问题:磁盘被打满,然后 io utils 高,触发业务监控告警,磁盘使用的是 HDD,出现问题的时候 iops 已经被打到几百、bps 也已经到了上百 MB/s,然后持续个几秒钟结束,然后过个几十秒又出现,这就造成了业务监控频繁告警。业务方会苦恼,磁盘被打满了到底是真实的业务需求量上来了呢?还是有什么野进程在占用 IO。比如之前碰到一例线上问题,平常都是正常的,突然某一天发现 IO 高了很多,然后客户想知道是谁把 IO 整高了,后面通过系统的各个命令组合 +ftrace 脚本统计,找到了贡献最高的进程来自于一个与业务不相关的容器,他会定时启动,谜一般的做大量的文件拷贝动作。

二、现有工具

在定位问题这类问题的过程中,我们会通过系统的现有工具,定位具体的进程、文件或者容器,然后采取下一步措施解决问题,如停掉进程、容器并查看问题现象是否消失。一般地,如下几类工具会使用比较频繁:

  • 基于内核 diskstats 衍生的工具,如 iostat、sar-类命令的IO统计功能、vmstat-d

——可以宏观的从整个磁盘角度去统计 io 信息,如统计整盘的 iops、bps

  • 基于内核 proc/$pid/io 衍生的工具,如 pidstat -d

——可以统计到进程贡献的总体IO

  • 基于 Taskstats 衍生的工具,如 iotop

——可以统计到进程贡献的总体 IO 以及贡献的 iowait

尽管系统为我们提供了比较丰富的工具,但总有这样一种感觉:使用已有的命令,尽管知道磁盘的 IO 高了,但不知道是哪个进程贡献的;知道系统里面的某个进程贡献的 IO 高了,但又不确定这里有多少 IO 是被我关心的磁盘给消费的,也不知道这些 IO 都是在操作什么文件,总觉得哪哪都差一点儿。所以总结下来,得到如下几点诉求:

● 在磁盘 IO 被打满的情况下,希望观察是哪个进程贡献了比较多的 IO

● 系统上统计到某个进程贡献了大量的 IO,希望观察到这些 IO 最终是被哪个磁盘给消费,或者这些 IO 是在访问哪个文件,如果这个进程是来自某个容器,希望依然可以获取访问的文件以及此进程所在的容器

而本文所介绍的 iofsstat,实现了从进程角度来统计 IO 信息、文件读写信息,满足了之前提到的几个诉求,可以应用到 io utils 高、io 打满类问题的定位中。

三、iofsstat 功能介绍

3.1 统计指定磁盘的进程文件 IO

主要统计某进程对某文件贡献了多少 IO,对用户呈现的指标为进程角度+磁盘角度,磁盘角度这个毋庸置疑是为了能够看到磁盘的全貌,进程角度,是更细粒度的,可以看到对应的在这个时刻,各进程的贡献情况(PS:这里并非进程贡献的总和要等于磁盘整体的统计,因为统计的原理不一致,这里可以更多的关注两个角度之间的关联性,如在某一时刻,磁盘统计到高了,这个时候可以看到对应的这个时刻的各个进程的贡献程度),各指标如下:

进程角度:

comm:进程名、pid:进程id、cnt_rd:读文件次数、bw_rd:读文件"带宽"、cnt_wr:写文件次数、bw_wr :写文件"带宽"、inode:文件inode编号、filepath:文件路径,当在一次采集周期内由于进程访问文件很快结束情况下,获取不到文件名则为"-"。

如进程来自某个容器,在文件名后缀会显示 [containterId:xxxxxx]

磁盘角度:

xxx-stat:r_iops:磁盘总的读 iops、xxx-stat:w_iops:磁盘总的写 iops、xxx-stat:r_bps:磁盘总的读 bps、xxx-stat:w_bps:磁盘总的写 bps、xxx-stat:wait:磁盘平均 io 延迟、xxx-stat:r_wait:磁盘平均读 io 延迟、xxx-stat:w_wait:磁盘平均写 io 延迟、xxx-stat:util%:磁盘 io utils

sysak iofsstat -d vdb1 --fs 1 #间隔1秒统计一次vdb磁盘上的进程读写文件情况

2022/01/19 14:13:48
vda-stat: r_iops w_iops r_bps w_bps wait r_wait w_wait util%
0.00 98.00 0.00 91.5MB/s 946.34 0.00 946.34 93.20 comm pid cnt_rd bw_rd cnt_wr bw_wr inode filepath
dd 55937 0 0 1096 137.0MB/s 9226 /home/data/tfatsf
...

显示结果按照 bw_rd 与 bw_wr 的和做降序排列,如输出结果较多想只看某进程情况下,可以使用 -p PID 只查看指定进程

此功能基于 surftrace 开发,surftrace 是在 ftrace 基础上封装的一系列工具集,用于 trace 内核信息,当前发行版主要包含 surftrace、surfGuide 两大工具,后期还将包含 pylcc(python libbpf compile collections)。更多详情参考可点击文末 surftrace 项目代码链接查看。

3.1.1 进程、磁盘、文件信息

因为复杂的 IO 软件栈,从用户态到落盘,IO 经历了不同的数据结构上的变化,同时经过 fs 和 block 之后,IO 的生产者也可能发生变化,因此在现有的条件下,无法做到不实现内核代码就可以直接获取到这些信息,我们所关注的信息仍需要在内核中解析某些数据结构体外加推演来获取,像获取文件名、IO 大小、进程信息等,比如我们通过在 block 层解析每个 io request 就可以获取到相当饱满的信息:

通过这种方式,首先可以捕捉到所有类别的 IO,也肯定可以获取 io 对应的文件信息,但是在 buffer io 情况下,需要在内核大动干戈的去轮询所有的 task 的 files strcut 反推得到实际写这个文件的进程,而且一旦进程已经关闭了这个文件,将会推导不出进程,因此不可取,另外应尽可能的避开内核 ko,避免后续使用上受限于内核版本问题;因此考虑 fs 层是否存在可用且稳定不会变化的 tracepoint。

实际上满足功能的需求,只需要获取进程信息、IO 大小、dev 编号、文件 inode 编号就够了,而在文件系统层没有现成的符合这些需求的 tracepoint,因此考虑通过 kprobe_events 去 hook 特定函数;kprobe_events 又绕不开因为不同内核版本,数据结构会不一致,造成输入到 kprobe_events 的表达式不一致的问题,幸运的是因为 surftrace 已经帮我们解决了这个问题,我们只需要关注 kprobe 之后数据的解析,而无需关注表达式的变化。

3.1.2 如何获取文件路径

通过 3.1.1 已经获取文件 inode 编号,通过 find -inum 指定磁盘的挂载目录,或者通过 debugfs 方式,获取到文件名,但这种方式不仅耗时间也可能会耗 io;因为已经获取到了进程信息,接下来可以在 /proc/$pid/fd 过滤出来属于指定磁盘下的文件,然后比对文件的 inode 即可获取文件名,简单高效,但缺点是当比对文件过程中文件访问结束被 close 掉了,就获取不到文件名了,但这种情况一般在有问题的情况下出现概率也很低(一般关注的 IO 打满问题基本持续时间也都是秒级别)。

3.2 统计指定磁盘的进程IO贡献

主要统计某进程对某磁盘贡献了多少 IO,对用户呈现的指标为进程角度+磁盘角度,磁盘角度这个毋庸置疑是为了能够看到磁盘的全貌,进程角度,是更细粒度的,可以看到对应的在这个时刻,各进程的贡献情况(PS:这里并非进程贡献的总和要等于磁盘整体的统计,因为统计的原理不一致,这里可以更多的关注两个角度之间的关联性,如在某一时刻,磁盘统计到高了,这个时候可以看到对应的这个时刻的各个进程的贡献程度),各指标如下:

进程角度:

comm:进程名、pid:进程 id、iops_rd:进程贡献的读 iops、bps_rd :进程贡献的读bps、iops_wr:进程贡献的写iops、bps_wr :进程贡献的写bps。

磁盘角度:

同 3.1 节磁盘角度。

sysak iofsstat -d vdb 1 #间隔1秒统计一次vdb磁盘上的进程io贡献情况

2022/01/19 12:04:38
vda-stat: r_iops w_iops r_bps w_bps wait r_wait w_wait util%
0.00 118.00 0.00 104.2MB/s 976.82 0.00 976.82 95.60 comm pid iops_rd bps_rd iops_wr bps_wr
[dd] 98675 1 4.0KB/s 259 32.4MB/s
[kworker/u12:0] 91022 1 4.0KB/s 198 167.5MB/s
[jbd2/vdb1-8] 19510 0 0 1 4.0KB/s
...

显示结果按照 iops_rd 与 iops_wr 的和做降序排列,如输出结果较多想只看某进程情况下,可以使用 -p PID 只查看指定进程,假设看到的是 kworker 类进程贡献的 io 最高,可以进一步通过 3.1 节功能从 fs 角度来查看是哪个进程、哪个文件的 IO 最多。

3.2.1 实现原理

此功能基于 block 的 tracepoint,可获取到指定磁盘的来自各进程的 IO 详细信息,然后统计每个进程的 iops、bps 贡献。

四、性能开销

iofsstat 本质上是基于 ftrace 的实现,不会引发宕机,可以放心使用,由于使用的 ftrace 基本内核版本稳定,因此对内核版本依赖性也低,性能开销方面,经过统计纯 IO 统计功能(3.2 节)开销单核 1% 以下,文件 IO 统计功能(3.1节)稍微高一点,0.x%~3.x%,还在优化。

五、代码开源

iofsstat 代码将在 3 月中旬开源,敬请期待。

Gitee sysak 代码仓链接:sysak: sysAK (system analyse kit) is a toolbox contains useful tools for linux SRE, such as problem diagnosing, events monitoring/tracing, and operating of system and service

surftrace 项目代码链接:https://github.com/aliyun/surftrace

系统运维 SIG 地址:sysom SIG - OpenAnolis 龙蜥操作系统开源社区

原文链接

本文为阿里云原创内容,未经允许不得转载。

iofsstat:帮你轻松定位 IO 突高,前因后果一目了然 | 龙蜥技术的更多相关文章

  1. 轻松定位CPU飙高问题

    以下四步轻松定位CPU飙高问题: ①top pid 查看cpu耗CPU进程 ②top -Hp pid 查看该进程所有线程的运行情况,找到占用 CPU 过高的线程 pid ③ printf %x pid ...

  2. IO负载高的来源定位

    前言: 在一般运维工作中经常会遇到这么一个场景,服务器的IO负载很高(iostat中的util),但是无法快速的定位到IO负载的来源进程和来源文件导致无法进行相应的策略来解决问题. 这个现象在MySQ ...

  3. iotop,pt-ioprofile : mysql IO负载高的来源定位

    http://www.cnblogs.com/cenalulu/archive/2013/04/12/3016714.html 前言: 在一般运维工作中经常会遇到这么一个场景,服务器的IO负载很高(i ...

  4. IO负载高的来源定位 IO系列

    http://elf8848.iteye.com/category/281637 前言: 在一般运维工作中经常会遇到这么一个场景,服务器的IO负载很高(iostat中的util),但是无法快速的定位到 ...

  5. IO负载高来源定位pt-ioprofile

    1.使用top -d 1 查看%wa是否有等待IO完成的cpu时间,简单理解就是指cpu等待磁盘写入完成的时间:IO等待所占用的cpu时间的百分比,高过30%时IO压力高: 2.使用iostat -d ...

  6. 嵌入式 如何定位死循环或高CPU使用率(linux) 及性能优化

    嵌入式 如何定位死循环或高CPU使用率(linux) ln -s /mnt/nfs/_install/usr/bin/sort /usr/bin/sort awk '{print $1,$2,$14, ...

  7. 【三板斧】Java定位CPU使用高问题

    [三板斧]Java定位CPU使用高问题 1.TOP命令,查询消耗CPU高的进程号 PID,并记录下来,按下键盘"H"键,记录高消耗线程号,并将改线程号转换为十六进制 2.使用 js ...

  8. Linux系统 磁盘IO过高排查总结

    最近做的一个电商网站因为磁盘 I/O 过高导致访问速度奇慢,问题存在两个月有余未得到解决办法.此次排查原因的经验可以作下次问题的参考. 1.会看懂 top 系统命令出来的各项参数.此次是无意中发现 u ...

  9. MySQL占用IO过高解决方案【转】

    1.日志产生的性能影响: 由于日志的记录带来的直接性能损耗就是数据库系统中最为昂贵的IO资源.MySQL的日志包括错误日志(ErrorLog),更新日志(UpdateLog),二进制日志(Binlog ...

  10. linux 磁盘io利用率高,分析的正确姿势

    一.背景简介 作为一个DBA难免不了会遇到性能问题,那么我们遇到性能问题该如何进行排查呢?例如我们在高并发的业务下,出现业务响应慢,处理时间长我们又该如何入手进行排查,本片文章将分析io高的情况下如何 ...

随机推荐

  1. decltype总结

    decltype会识别const和引用 decltype一个表达式的时候会判断该表达式是左值还是右值,如果是左值就返回引用,否则就返回非引用. int &a = xx; const declt ...

  2. 20_使用SDL显示BMP图片

    文本的主要内容是:使用SDL显示一张BMP图片,算是为后面的<显示YUV图片>做准备. 为什么是显示BMP图片?而不是显示JPG或PNG图片? 因为SDL内置了加载BMP的API,使用起来 ...

  3. Ubuntu(Linux) PyQt5 QtUIFile 转换为 PythonModule (pyuic.py/pyuic脚本)

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明   本文作为本人csdn blog的主站的备份.(Bl ...

  4. eviacam在Arch/Manjaro Linux下的安装

    安装base-devel 安装编译工具,默认的依赖里没有编译工具 sudo yay -S base-devel 如果安装编译工具,会报类似下面的错误: 安装eviacam yay -S eviacam ...

  5. 记录--Vue开发历程---音乐播放器

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 一.audio标签的使用 1.Audio 对象属性 2.对象方法 二.效果 效果如下: 三.代码 代码如下: MusicPlayer.vu ...

  6. Spring Boot框架中使用Jackson的处理总结

    1.前言 通常我们在使用Spring Boot框架时,如果没有特别指定接口的序列化类型,则会使用Spring Boot框架默认集成的Jackson框架进行处理,通过Jackson框架将服务端响应的数据 ...

  7. C# Image 图片缩放 截取

    从大图中截取一部分图片 /// <summary> /// 从大图中截取一部分图片 /// </summary> /// <param name="fromIm ...

  8. MySQL插入更新删除数据

    数据插入 插入完整的行 INSERT INTO customers VALUES(NULL, 'Pep E. LaPew', '100 Main Street', 'Los Angeles', 'CA ...

  9. .Net单元测试xUnit和集成测试指南(1)

    引言 在现代化的软件开发中,单元测试和集成测试是确保代码质量和可靠性的关键部分.ASP.NET Core 社区内提供了强大的单元测试框架,xUnit 是其中之一,它提供了简单.清晰和强大的测试功能,编 ...

  10. #最大公约数#CF346A Alice and Bob

    题目传送门 CF346A 分析 可以发现其所能表示的数就是能被最大公约数整除的数,且这些数不能超过最大值, 于是判断一下取数的奇偶性即可 代码 #include <cstdio> #inc ...