CPU.IOWAIT 偏高问题《二》

写在前面

今天是 2018 年 01 月 04 号,已经是 2018 年的第四天了,最近这几天一直在做年终总结,回顾自己整年的工作,成长,问题,计划新的一年。2017年对于我来说,”tough year”!发生了太多的事,太多太多的事,开心的,烦恼的,2017年初计划的事情没有一件让我自己满意,想想嘘嘘不已!

这几天好好的写一篇总结!2018年对我来说,很重要!

回顾一下

上一篇文章 CPU.IOWAIT 偏高问题中其实已经大致分析出了问题所在。

文中『Find The Murderer』章节也指出了可能造成 IOWAIT% 偏高的进程,但不够有说服力。故此文尝试进一步的分析造成 IOWAIT% 偏高的原因!

查找最耗 IOWAIT 的进程

造成 IOWAIT% 偏高的进程一定也是 I/O 操作比较频繁的进程,CPU.IOWAIT 偏高问题中使用了两种方法,第一种是使用 ps 命令查找状态码为 ‘D’ 的进程,这种方式找到的结果不够准确;第二种是使用 iotop 工具,这种方式可能存在的问题是机器内核版本定制过,部分模块可能没有,而 iotop 这个工具要求内核版本相对较高,虽然我做了一点修改,骗过了 iotop,让 iotop 能正常运行,但总之得到的结果可能不够准确。

基于以上的分析,有必要用另外的方法。那么如何统计每个进程的 I/O 数呢,进而找到 I/O 数最高的进程?下面是查找过程。

首先,关闭syslog:

1
2
dmesg -c
/etc/init.d/klogd stop

接着下载一个 perl 脚本:

1
wget https://github.com/true/aspersa-mirror/blob/master/iodump

然后,打开 block_dump,这是内核关于 I/O 信息的一些日志:

1
echo 1 > /proc/sys/vm/block_dump

block_dump中设置非零值能够打开内核关于每一个 I/O 操作进行记录的开关,这时候可以看到内核已经收集到了 I/O 的日志:

1
2
3
4
5
6
[root@localhost]# dmesg
someprocess(1880): READ block 3830529728 on bcache1 (160 sectors)
someprocess(1877): READ block 2492278208 on bcache2 (160 sectors)
someprocess(1878): READ block 1407266528 on bcache3 (160 sectors)
someprocess(1877): WRITE block 2671126368 on bcache2 (160 sectors)
someprocess(1877): WRITE block 2671126528 on bcache2 (160 sectors)

接下来就是对这些日志进行分析,这时就用到了 iodump 脚本:

1
while true; do sleep 1; dmesg -c; done | perl iodump

这时候可能会出错:

1
-bash: perl: command not found

oho,这台机器没有 perl 环境,好吧,接着装一个好了:

1
2
3
4
5
6
7
wget http://www.cpan.org/src/5.0/perl-5.26.1.tar.gz
tar zxvf perl-5.26.1.tar.gz
cd perl-5.26.1

./Configure -des -Dprefix=./localperl
make test
make install

然后添加环境变量:

1
export PATH=$PATH:/root/mydir/localperl/bin

重新执行命令:

1
while true; do sleep 1; dmesg -c; done | perl iodump

又抛错了?纳尼?

1
Can't locate strict.pm in @INC (you may need to install the strict module) (@INC contains: /root/mydir/localperl/lib/site_perl/5.20.1/x86_64-linux /root/mydir/localperl/lib/site_perl/5.20.1 /root/mydir/localperl/lib/5.20.1/x86_64-linux /root/mydir/localperl/lib/5.20.1 .) at iodump line 34.

好吧,设置下库路径:

1
export PERL5LIB=$PERL5LIB:/root/mydir/localperl/lib

重新运行命令,正常的话可以看到下面的输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root@localhost]# while true; do sleep 1; dmesg -c; done | ./localperl/bin/perl iodump
TASK PID TOTAL READ WRITE DIRTY DEVICES
someproce 1877 7236 5923 1313 0 sda3
someproce 1879 7206 5877 1329 0 sda3
jbd2/sda3-8 1241 235 0 235 0 sda3
kworker/u16:2 949469 84 0 84 0 sda3, sda1
jbd2/sda1-8 509 82 0 82 0 sda1
edge-speeds-ale 1265169 3 0 3 0 sda3
falcon-agent 4144 2 0 2 0 sda3
falcon-agent 1831 1 0 1 0 sda3
wc 1266086 1 0 1 0 sda3
curl 1266655 1 0 1 0 sda3
curl 1265033 1 0 1 0 sda3
wc 1266089 1 0 1 0 sda3
falcon-agent 116709 1 0 1 0 sda3
bash 1264583 1 0 1 0 sda1
falcon-agent 4142 1 0 1 0 sda3
wc 1266083 1 0 1 0 sda3
falcon-agent 4150 1 0 1 0 sda3
falcon-agent 116710 1 0 1 0 sda3

统计结果很明白了,I/O 频繁的进程自然是导致 IOWAIT% 偏高的原因,那么根本原因还是硬件性能不足,磁盘 SSD 性能退化问题。

告一段落

CPU.IOWAIT 偏高问题以及本篇文章,做了很多关于 I/O、CPU、磁盘的比较细的研究,这些手段和方法值得以后排查其他问题借鉴!

参考

buy me a cola!

欢迎关注我的其它发布渠道