iofsstat:帮你轻松定位 IO 突高,前因后果一目了然 | 龙蜥技术
简介:磁盘被打满到底是真实的业务需求量上来了呢?还是有什么野进程在占用 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 月中旬开源,敬请期待。
surftrace 项目代码链接:https://github.com/aliyun/surftrace
系统运维 SIG 地址:sysom SIG - OpenAnolis 龙蜥操作系统开源社区
本文为阿里云原创内容,未经允许不得转载。
iofsstat:帮你轻松定位 IO 突高,前因后果一目了然 | 龙蜥技术的更多相关文章
- 轻松定位CPU飙高问题
以下四步轻松定位CPU飙高问题: ①top pid 查看cpu耗CPU进程 ②top -Hp pid 查看该进程所有线程的运行情况,找到占用 CPU 过高的线程 pid ③ printf %x pid ...
- IO负载高的来源定位
前言: 在一般运维工作中经常会遇到这么一个场景,服务器的IO负载很高(iostat中的util),但是无法快速的定位到IO负载的来源进程和来源文件导致无法进行相应的策略来解决问题. 这个现象在MySQ ...
- iotop,pt-ioprofile : mysql IO负载高的来源定位
http://www.cnblogs.com/cenalulu/archive/2013/04/12/3016714.html 前言: 在一般运维工作中经常会遇到这么一个场景,服务器的IO负载很高(i ...
- IO负载高的来源定位 IO系列
http://elf8848.iteye.com/category/281637 前言: 在一般运维工作中经常会遇到这么一个场景,服务器的IO负载很高(iostat中的util),但是无法快速的定位到 ...
- IO负载高来源定位pt-ioprofile
1.使用top -d 1 查看%wa是否有等待IO完成的cpu时间,简单理解就是指cpu等待磁盘写入完成的时间:IO等待所占用的cpu时间的百分比,高过30%时IO压力高: 2.使用iostat -d ...
- 嵌入式 如何定位死循环或高CPU使用率(linux) 及性能优化
嵌入式 如何定位死循环或高CPU使用率(linux) ln -s /mnt/nfs/_install/usr/bin/sort /usr/bin/sort awk '{print $1,$2,$14, ...
- 【三板斧】Java定位CPU使用高问题
[三板斧]Java定位CPU使用高问题 1.TOP命令,查询消耗CPU高的进程号 PID,并记录下来,按下键盘"H"键,记录高消耗线程号,并将改线程号转换为十六进制 2.使用 js ...
- Linux系统 磁盘IO过高排查总结
最近做的一个电商网站因为磁盘 I/O 过高导致访问速度奇慢,问题存在两个月有余未得到解决办法.此次排查原因的经验可以作下次问题的参考. 1.会看懂 top 系统命令出来的各项参数.此次是无意中发现 u ...
- MySQL占用IO过高解决方案【转】
1.日志产生的性能影响: 由于日志的记录带来的直接性能损耗就是数据库系统中最为昂贵的IO资源.MySQL的日志包括错误日志(ErrorLog),更新日志(UpdateLog),二进制日志(Binlog ...
- linux 磁盘io利用率高,分析的正确姿势
一.背景简介 作为一个DBA难免不了会遇到性能问题,那么我们遇到性能问题该如何进行排查呢?例如我们在高并发的业务下,出现业务响应慢,处理时间长我们又该如何入手进行排查,本片文章将分析io高的情况下如何 ...
随机推荐
- SpringMVC异常之The request sent by the client was syntactically incorrect解决方案
最近在做SpringMVC开发的时候,直接访问后台的controller,出现如下异常 这个问题是什么原因造成的呢? 后来经过测试发现,是表单提交的内容数据类型与实体的(也就是数据表字段)的数据类型不 ...
- Grails批改默认启动端口
Grails修改默认启动端口 Grails默认启动端口号是8080,有几种修改的方式: 一.在官网文档中有介绍: grails -Dserver.port=8090 run-app -Dserver. ...
- terminate called after throwing an instance of 'std::regex_error'(C++11)
PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明 本文作为本人csdn blog的主站的备份.(Bl ...
- Android 开发Day2
我的是小刺猬版本,算是比较新的版本了,还有火烈鸟和蜻蜓版啥的 新建项目(project)点击加号新建就行了.这时我们会选择一个模板作为开发的辅助起点,看上哪个就选哪个就行了.推荐新手选空项目(Empt ...
- django(图书管理系统)
一.表的设计 from django.db import models # Create your models here. class Book(models.Model): title = mod ...
- 记录--Echarts绘制气泡图
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 Echarts绘制气泡图 气泡图是一种用于可视化三维数据的图表类型,其中两个变量用于确定数据点在平面上的位置,另一个变量用于确定气泡的大小 ...
- 记录--webpack和vite原理
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前言 每次用vite创建项目秒建好,前几天用vue-cli创建了一个项目,足足等了我一分钟,那为什么用 vite 比 webpack 要快 ...
- NSSCTF—Crypyo "第一页" ԅ(≖‿≖ԅ) (待续……)
[鹤城杯 2021]easy_crypto 题目: 公正公正公正诚信文明公正民主公正法治法治诚信民主自由敬业公正友善公正平等平等法治民主平等平等和谐敬业自由诚信平等和谐平等公正法治法治平等平等爱国和谐 ...
- KingbaseES 数据插入更新操作
数据库使用过程中,经常会遇到一种场景:业务系统对数据进行dml操作,当数据库中数据不存在时,将数据做为新记录插入到表中,当数据库中数据存在时,对现有数据进行更新操作. 下面介绍KingbaseES中对 ...
- KingbaseES V8R3 表加密
前言 透明加密是指将数据库page加密后写入磁盘,当需要读取对应page时进行加密读取.此过程对于用户是透明, 用户无需干预. 该文档进行数据库V8R3版本测试透明加密功能,需要说明,该版本发布时间早 ...