Linux

一则利用bcc工具包的filetop和opensnoop工具跟踪IO的案例

一 背景说明

两台机器,在server1上运行一个Docker容器,跑的是Python程序的Flask应用,提供一个访问单词热度的接口;server2(172.16.17.36)向server1发起请求调用。

这个案例有意思的是,从server1上明明看到有消耗高CPU资源和磁盘IO的进程,但是,不太直观的看到该进程具体读写的是哪个文件。于是,这里给出不同的分析思路和解决方案。

server1: 172.16.17.7,4C 8G;

server2: 172.16.11.36,24C 64G;

二 分析步骤和思路

1 server1启动container

2 server2验证服务正常

3 server2向server1发起请求

curl http://172.16.17.7:10000/popularity/word

发现响应特别慢。

4 server1 查看top

发现server1 的进程26611耗费了比较高的CPU资源,top界面按下c字符键,调出进程执行的命令,看到该进程执行了/usr/local/bin/python /app.py 。

5 server1通过iostat查看系统IO资源情况

通过iostat -dx 1; -d 列出磁盘设备利用率;-x 列出extended statistics ;数字1,每秒输出1个报告;

持续观察,可以看到,系统的磁盘使用率有抖动,%util有时会达到100%,如上。iops(r/s+w/s)以及throughout(rkB/s+wkB/s)也会明显的变化。这意味着,系统的磁盘IO使用率会随着客户端发起请求,持续升高。那么,究竟是哪个进程在消耗较高的磁盘IO呢?

6 pidstat跟踪server1上进程的IO使用情况

pidstat -d,列出进程磁盘使用率信息:

的确,看到26611进程的磁盘IO比较高。

7 strace跟踪进程26611的读写文件

并没有看到进程26611对应的读写文件。怎么办呢?有没有其它思路?

8 通过BCC的filetop来跟踪

由于在操作系统层面并没有跟踪到进程26611实际读写的文件是哪个?我们通过BCC的filetop来跟踪内核里读写文件的信息

安装BCC(BPF Compiler Collection)工具包,调用其filetop查看File reads and writes by filename and process。

安装之后,位于/usr/share/bcc/tools路径下:-C表示当前屏幕不清屏的方式持续输出,第1列,表示线程号,COMM线程执行的命令,READS+WRITES分别表示读写次数,R_Kb、W_Kb表示的是读写的大小,T表示方式,R是Read,FILE列,表示的读写的文件名。

9 BCC的opensnoop查看内核open执行的系统调用

同样使用BCC工具包下提供的另一个工具,opensnoop。

这次,可以看到26611进程读取的文件的路径,持续跟踪,发现文件的路径会发生变化。大概率猜测一下,可能是前面的Python进程,在创建临时文件,然后操作处理之后,删除了文件。

10 查看Docker 应用代码

进入container内部,查看app.py源代码:

的确,发现了创建临时目录和文件,然后处理之后,再删除的操作。

三 小结

1 分析思路

  • 先top看到高CPU的进程;
  • 然后,iostat -dx 1;查看系统IO
  • 接下来,pidstat -d -p pid 1 ;查看指定进程的磁盘IO开销;
  • 想要通过strace -p pid;找到进程读写的文件信息未果;
  • 到此,转而使用BCC工具包的filetop查看内核中的文件读写信息,找到基本的文件名等读写相关信息;
  • 最后,继续使用BCC工具包的opensnoop工具查看内核中open调用的栈信息;

2 另外一种思路

使用strace -f -p pid;可以跟踪进程及其线程的读写信息:

3 个人收获

学习到strace -f -p pid;可以跟踪进程以及其线程的文件读写信息;

学会安装使用BCC工具包中的filetop跟踪内核中文件读写信息;opensnoop;跟踪内核中使用open系统调用的栈信息。

4 关于filetop和opensnoop的使用帮助

可以分别加上-h命令行查看,或者到GitHub站点查看相关示例。

四 参考和链接

1 倪朋飞老师的Linux性能优化实战,27 | 案例篇:为什么我的磁盘I/O延迟很高?;

2 BPF Compiler Collection

3 Installing BCC