前一阵产品升级Linux kernel的版本,升级后版本号是2.6.32-100.24.1.el5。
QA在vmWare上运行扩充磁盘空间时,偶尔会发现console上打出一堆kernel的异常信息,如下图
关键信息就是“hung_task_timeout_secs",第一次遇到kernel的问题,而且这个kernel是我们自己从源码build出来的,也拿不准是哪里的问题,于是开始google...
找了半天,终于大概弄明白了,这应该是Linux kernel的一个bug,在redhat和centos的bugzilla中都能找到跟踪号,而且很多人都在讨论,但是似乎Linux的人不把这个问题当回事,问题出了很久也没有修改,或许他们认为是用户的使用问题。
https://bugzilla.redhat.com/show_bug.cgi?id=605444#c43
http://bugs.centos.org/view.php?id=4515
http://www.centos.org/modules/newbb/viewtopic.php?topic_id=36408&forum=55
网上找的一段解释:
By default Linux uses up to 40% of the available memory for file system caching.
After this mark has been reached the file system flushes all outstanding data to disk causing all following IOs going synchronous.
For flushing out this data to disk this there is a time limit of 120 seconds by default.
In the case here the IO subsystem is not fast enough to flush the data withing 120 seconds.
This especially happens on systems with a lot of memory.
The problem is solved in later kernels
意思就是说,一般情况下Linux写磁盘时会用到缓存,这个缓存大概是内存的40%,只有当这个缓存差不多用光时,系统才会将缓存中的内容同步写到磁盘中。但是操作系统对这个同步过程有一个时间限制,就是120秒。如果系统IO比较慢,在120秒内搞不定,那就会出现这个异常。这通常发生在内存很大的系统上。
原因找到了,怎么解决呢?网上也有一些方案,比如
1. /sbin/sysctl -w vm.dirty_ratio=10
2. echo noop > /sys/block/sda/queue/scheduler
3. /sbin/sysctl -w kernel.hung_task_timeout_secs = 0
第一个方案是调整缓存占内存的比例,降到10%,这样的话较少的缓存内容会被比较频繁地写到硬盘上,IO写会比较平稳
第二个方案是修改系统的IO调度策略,使用noop的方式,这是一种基于FIFO的最简单的调度方式
第三个方案是不让系统有那个120秒的时间限制,希望就是我慢就慢点,你等着吧,实际上操作系统是将这个变量设为长整形的最大值。
这三个方案好像都很有道理,应该能搞定这个吧?但是,往往事与愿违,这三种方案经QA验证后一个也没发挥作用,问题依旧偶尔出现。
百思不得姐
,但是肯定是因为磁盘IO繁忙导致的系统故障,因为故障出现时,JBoss正在启动,vmWare还在扩展磁盘空间。自己写个脚本跑跑看:
QA在vmWare上运行扩充磁盘空间时,偶尔会发现console上打出一堆kernel的异常信息,如下图
关键信息就是“hung_task_timeout_secs",第一次遇到kernel的问题,而且这个kernel是我们自己从源码build出来的,也拿不准是哪里的问题,于是开始google...
找了半天,终于大概弄明白了,这应该是Linux kernel的一个bug,在redhat和centos的bugzilla中都能找到跟踪号,而且很多人都在讨论,但是似乎Linux的人不把这个问题当回事,问题出了很久也没有修改,或许他们认为是用户的使用问题。
https://bugzilla.redhat.com/show_bug.cgi?id=605444#c43
http://bugs.centos.org/view.php?id=4515
http://www.centos.org/modules/newbb/viewtopic.php?topic_id=36408&forum=55
网上找的一段解释:
By default Linux uses up to 40% of the available memory for file system caching.
After this mark has been reached the file system flushes all outstanding data to disk causing all following IOs going synchronous.
For flushing out this data to disk this there is a time limit of 120 seconds by default.
In the case here the IO subsystem is not fast enough to flush the data withing 120 seconds.
This especially happens on systems with a lot of memory.
The problem is solved in later kernels
意思就是说,一般情况下Linux写磁盘时会用到缓存,这个缓存大概是内存的40%,只有当这个缓存差不多用光时,系统才会将缓存中的内容同步写到磁盘中。但是操作系统对这个同步过程有一个时间限制,就是120秒。如果系统IO比较慢,在120秒内搞不定,那就会出现这个异常。这通常发生在内存很大的系统上。
原因找到了,怎么解决呢?网上也有一些方案,比如
1. /sbin/sysctl -w vm.dirty_ratio=10
2. echo noop > /sys/block/sda/queue/scheduler
3. /sbin/sysctl -w kernel.hung_task_timeout_secs = 0
第一个方案是调整缓存占内存的比例,降到10%,这样的话较少的缓存内容会被比较频繁地写到硬盘上,IO写会比较平稳
第二个方案是修改系统的IO调度策略,使用noop的方式,这是一种基于FIFO的最简单的调度方式
第三个方案是不让系统有那个120秒的时间限制,希望就是我慢就慢点,你等着吧,实际上操作系统是将这个变量设为长整形的最大值。
这三个方案好像都很有道理,应该能搞定这个吧?但是,往往事与愿违,这三种方案经QA验证后一个也没发挥作用,问题依旧偶尔出现。
百思不得姐
![抓狂](http://static.blog.csdn.net/xheditor/xheditor_emot/default/crazy.gif)
#!/usr/bin/perl
use strict;
use warnings;
use POSIX qw(setsid);
my $i = 0;
for ($i=0; $i < 1000; $i++) {
if (my $pid = fork()) {
}else {
setsid or die "can not start a new session: $!";
close (STDOUT);
`nice -n -20 /bin/dd if=/dev/zero of=/var/iotest."$i" bs=4M count=10 oflag=direct` ;
exit 0;
}
}
发现如果dd命令带着”oflag=direct"参数,问题就会出现,去掉就没问题。JBoss启动时有大量的MySQL读写,检查了产品用的MySQL配置文件,发现有这么一个配置:innodb_flush_method=O_DIRECT。什么是Direct IO呢,这里就不多说了,自己上网搜吧。
让QA把这个参数改成默认参数,问题消失了,但是QA说不能改这个参数,会影响系统性能。。。无语。。。
最后的workaround是扩展磁盘空间时,先把JBoss、MySQL都停掉,扩展完后再启动