在Linux中 IO操作过高会使系统性能下降甚至会导致某些进程出现卡死,段错误,系统重启,等不良现象。下面我们来介绍一下如何监控IO并且在IO操作过高时,我们应该怎么定位与处理。
判断IO是否高
我们使用iostat工具监控IO状态,通常我比较喜欢使用:
iostat -x -t 1
图中sda 的util%才18%这样,如果util百分比很高,表示磁盘忙,该值的意义为磁盘io带宽利用率,即1秒内,有多少时间没有需要处理的io请求。await表示一个io请求要等多久才能被处理,svctm表示处理一个请求要多久,这个值可以反映磁盘性能。
使用top命令判断IO
步骤: top,ENTER,按1, 按F, 按J, ENTER,CTRL+H 查看cpu处于wa,sy的时间比例,高则可能io操作异常。
此方法不一定准,cpu的wa仅表示等待Io的cpu时间比例,如果系统有别的不须io的进程,处于此状态的cpu会切换去处理那些进程,使此值有变动。
如何判断导致io 过高的线程
根据上面的图片中,通过top查看那些cpu的wa高,然后看查看运行于该cpu的线程里那些处于D状态的概率高,可以判断哪个线程引起io过高。需要注意,内核线程如flush-0/kswapd0通常会是io过高的线程,但是它不是根本原因,是Io过高导致它们运行的,只有用户线程才是引起io高的根本原因。
注意:D状态为不可中断等待状态,处于IO等待比处于D状态,但是D状态不一定都由IO引起,死锁等也会引起,S为可中断等待状态.
另一个找出io高线程的方法
上面的方法简便,但有局限性. io操作均处于内核函数中,可以输出内核的调用栈,查看那些线程在做io操作,步骤如下。
1、 打开sysrq功能:
echo 1 > /proc/sys/kernel/sysrq
2、 清空内核log缓存:
dmesg -c
信息太多,只截屏了一半。
3、输出内核栈
echo “t” > /proc/sysrq-trigger
4、输出内核栈到文件
dmesg > k.log
5、查找那些线程处于D状态
cat k.log |grep ’ D ’
最后去除内核线程,查看处于D状态线程的调用栈,看最顶层函数是否为sys_write和sys_read等,去掉那些不是io 的线程,如缺页,锁等导致的就不是。
定位IO忙进程的代码片段
导致IO高的线程找到了,下一步是查找io高的代码。
方法:
查看产生问题进程的调用栈:
gstack $(pidof 进程名) > g.log
然后查找0栈为read,write等io函数的调用栈,由这些栈进一步查看代码。
进程长期处于D状态导致系统重启问题的定位与处理
进程长期处于D状态,即不可中断等待状态,必须由代码编写者主动调用相关函数才会退出该状态,操作系统不会主动去干预这些进程,因此这些进程kill不掉。
长期处于D状态的危害
进程长期处于D状态处理该进程本身功能失效外,还会导致其他的进程处于D状态,使系统慢慢切底死掉,最后导致要进机房重启机器。
其原因为,处于D状态的进程获取了一个内核锁不释放,如果后面有进程再获取该锁的话,也会死在上面,这个新的进程本身也会获取一些其他的锁,这样就导致连锁反应,如果sshd死掉则系统不能当录。
导致D状态的原因
一般由io等待,死锁,或锁被长期占用引起。
那我们如何处理呢?
没有好的处理办法,只有启动内核的自动检测功能,一旦处于D状态太久,则panic自动重启,开启办法:
echo “1” > /proc/sys/kernel/panic 内核panic后1秒重启
echo “1” > /proc/sys/kernel/hung_task_panic 处于D状态后产生panic
echo “3600” > /proc/sys/kernel/hung_task_timeout_secs 检测一个进程处于D状态的时间,超过此值则执行panic
注意:hung_task_timeout_secs这个值很重要,不能太小,都这一些io操作稍长一点的动作都会引起系统重启。
查找原因
处于D状态后,按前述方法输出内核调用栈,查看对应进程的内核栈,分析问题原因,需要区分是否由io忙引起,如果是io忙引起,则是一个性能问题,需在用户层优化,否则是内核模块问题,特别需要怀疑第三方内核模块,如加速卡启动等。
欢迎关注微信公众号【程序猿编码】,添加本人微信号(17865354792),回复:领取学习资料。或者回复:进入技术交流群。网盘资料有如下: