OOM续

最近维护测试服务器越来越多出现OOM。每次都是改改内核参数,貌似有点用处。但是这个治标不治本,源头没有找到。

自己先了解了一下一些基础性的东西。每次OOM后查看messages日志都能看到

[text]

<span>Jun 18 17:10:23 free-72-222 kernel: oom-killer: gfp_mask=0xd0
Jun 18 17:10:23 free-72-222 kernel: Mem-info:
Jun 18 17:10:23 free-72-222 kernel: DMA per-cpu:
Jun 18 17:10:23 free-72-222 kernel: cpu 0 hot: low 2, high 6, batch 1
Jun 18 17:10:23 free-72-222 kernel: cpu 0 cold: low 0, high 2, batch 1
Jun 18 17:10:23 free-72-222 kernel: cpu 1 hot: low 2, high 6, batch 1
Jun 18 17:10:23 free-72-222 kernel: cpu 1 cold: low 0, high 2, batch 1
Jun 18 17:10:23 free-72-222 kernel: cpu 2 hot: low 2, high 6, batch 1
Jun 18 17:10:27 free-72-222 kernel: cpu 2 cold: low 0, high 2, batch 1
Jun 18 17:10:27 free-72-222 kernel: cpu 3 hot: low 2, high 6, batch 1
Jun 18 17:10:27 free-72-222 kernel: cpu 3 cold: low 0, high 2, batch 1
Jun 18 17:10:27 free-72-222 kernel: Normal per-cpu:
Jun 18 17:10:27 free-72-222 kernel: cpu 0 hot: low 32, high 96, batch 16
Jun 18 17:10:27 free-72-222 kernel: cpu 0 cold: low 0, high 32, batch 16
Jun 18 17:10:27 free-72-222 kernel: cpu 1 hot: low 32, high 96, batch 16
Jun 18 17:10:27 free-72-222 kernel: cpu 1 cold: low 0, high 32, batch 16
Jun 18 17:10:27 free-72-222 kernel: cpu 2 hot: low 32, high 96, batch 16
Jun 18 17:10:27 free-72-222 kernel: cpu 2 cold: low 0, high 32, batch 16

Jun 20 14:46:44 free-72-222 kernel: cpu 2 cold: low 0, high 32, batch 16
Jun 20 14:46:44 free-72-222 kernel: cpu 1 cold: low 0, high 32, batch 16
Jun 20 14:46:44 free-72-222 kernel: cpu 2 hot: low 32, high 96, batch 16
Jun 20 14:46:44 free-72-222 kernel: cpu 2 cold: low 0, high 32, batch 16
Jun 20 14:46:44 free-72-222 kernel: cpu 3 hot: low 32, high 96, batch 16
Jun 20 14:46:44 free-72-222 kernel: cpu 3 cold: low 0, high 32, batch 16
Jun 20 14:46:44 free-72-222 kernel:
Jun 20 14:46:44 free-72-222 kernel: Free pages:       35748kB (24320kB HighMem)
Jun 20 14:46:44 free-72-222 kernel: protections[]: 0 0 0
Jun 20 14:46:44 free-72-222 kernel: protections[]: 0 0 0
Jun 20 14:46:44 free-72-222 kernel: protections[]: 0 0 0
Jun 20 14:46:44 free-72-222 kernel: protections[]: 0 0 0
Jun 20 14:46:44 free-72-222 kernel: Normal free:3304kB min:3336kB low:6672kB high:10008kB active:617956kB inactive:0kB pre
sent:729088kB pages_scanned:1293 all_unreclaimable? no
Jun 20 14:46:44 free-72-222 kernel: protections[]: 0 0 0
Jun 20 14:46:44 free-72-222 kernel: HighMem free:24320kB min:512kB low:1024kB high:1536kB active:2836904kB inactive:486976
kB present:3358720kB pages_scanned:0 all_unreclaimable? no
Jun 20 14:46:44 free-72-222 kernel: protections[]: 0 0 0
Jun 20 14:46:44 free-72-222 kernel: DMA: 3*4kB 2*8kB 6*16kB 4*32kB 5*64kB 1*128kB 1*256kB 2*512kB 2*1024kB 2*2048kB 0*4096
kB = 8124kB
Jun 20 14:46:44 free-72-222 kernel: Normal: 0*4kB 1*8kB 0*16kB 1*32kB 1*64kB 1*128kB 0*256kB 0*512kB 1*1024kB 1*2048kB 0*4
096kB = 3304kB
Jun 20 14:46:44 free-72-222 kernel: HighMem: 5942*4kB 5*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 1*512kB 0*1024kB 0*2048kB
 0*4096kB = 24320kB
Jun 20 14:46:44 free-72-222 kernel: 428935 pagecache pages
Jun 20 14:46:44 free-72-222 kernel: Swap cache: add 0, delete 0, find 0/0, race 0+0
Jun 20 14:46:44 free-72-222 kernel: 0 bounce buffer pages
Jun 20 14:46:44 free-72-222 kernel: Free swap:            0kB
Jun 20 14:46:44 free-72-222 kernel: 1026048 pages of RAM
Jun 20 14:46:44 free-72-222 kernel: 839680 pages of HIGHMEM
Jun 20 14:46:44 free-72-222 kernel: 10594 reserved pages
Jun 20 14:46:44 free-72-222 kernel: 413640 pages shared
Jun 20 14:46:44 free-72-222 kernel: 0 pages swap cached
Jun 20 14:46:44 free-72-222 kernel: Out of Memory: Killed process 19148 (java).</span>

[/text]

这样的日志,对于里面的

[text]

Jun 20 14:46:44 free-72-222 kernel: DMA: 3*4kB 2*8kB 6*16kB 4*32kB 5*64kB 1*128kB 1*256kB 2*512kB 2*1024kB 2*2048kB 0*4096
kB = 8124kB
Jun 20 14:46:44 free-72-222 kernel: Normal: 0*4kB 1*8kB 0*16kB 1*32kB 1*64kB 1*128kB 0*256kB 0*512kB 1*1024kB 1*2048kB 0*4
096kB = 3304kB
Jun 20 14:46:44 free-72-222 kernel: HighMem: 5942*4kB 5*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 1*512kB 0*1024kB 0*2048kB
 0*4096kB = 24320kB

[/text]

就能看出OOM发生的当时实际的Normal,HigMem的空闲内存值分布是 2304KB,24320KB。

另外我们也可以根据

[text]

# cat /proc/buddyinfo
Node 0, zone      DMA      3      2      6      4      5      1      1      2      2      2      0
Node 0, zone   Normal     28      1      1      1   2413    918    161     12      1      1      0
Node 0, zone  HighMem    126   8173  18550   1254     22      0      0      1      0      0      0

[/text]

查看系统当前的内存情况。对于buddyinfo  的解释参考

http://www.centos.org/docs/5/html/5.2/Deployment_Guide/s2-proc-buddyinfo.html

对于messages日志

其实就是

第1列*4kB 第2列*8kB 第3列*16kB 第4列*32kB 第5列*64kB 第6列*128kB 第7列*256kB 第8列*512kB 第9列*1024kB 第10列*2048kB 第11列*4096kB

总的和就是当时剩余的内存值。

我们可以使用命令

echo m > /proc/sysrq-trigger

让内核把当前的buddyinfo信息打印到messages日志中

[text]

<span># cat /proc/buddyinfo    ;echo m > /proc/sysrq-trigger
Node 0, zone      DMA      3      2      6      4      5      1      1      2      2      2      0
Node 0, zone   Normal      0      0      0      1   2403    918    161     12      1      1      0
Node 0, zone  HighMem      0      0  18372   1254     22      0      0      1      0      0      0</span>

<span>[root@test1 /var/log]
# grep Normal: /var/log/messages |tail -n 1
Jun 20 15:44:39 free-72-222 kernel: Normal: 0*4kB 2*8kB 1*16kB 0*32kB 2410*64kB 918*128kB 161*256kB 12*512kB 1*1024kB 1*2048kB 0*4096kB = 322208kB</span>

<span>[root@test1/var/log]
# grep HighMem: /var/log/messages |tail -n 1
Jun 20 15:44:39 free-72-222 kernel: HighMem: 0*4kB 0*8kB 18372*16kB 1254*32kB 22*64kB 0*128kB 0*256kB 1*512kB 0*1024kB 0*2048kB 0*4096kB = 336000kB</span>

[/text]

这里面空闲的内存值加起来和free的结果是一直的

[text]

<span># free -m
                   total       used       <span>free</span>     shared    buffers     cached
Mem:          4000       3351        <span>648</span>          0        257       2046
-/+ buffers/cache:       1047       2952
Swap:            0             0              0</span>

[/text]

再回到系统对进程内存分配控制的2个内核参数

/proc/sys/vm/overcommit_memory 可以有个三个值

[text]

0 (default): as before: guess about how much overcommitment is reasonable,

1: never refuse any <code>malloc()</code>,

2: be precise about the overcommit – never commit a virtual address space larger than swap space plus a fraction <code>overcommit_ratio</code> of the physical memory. Here <code>/proc/sys/vm/overcommit_ratio</code> (by default 50) is another user-settable parameter. It is possible to set <code>overcommit_ratio</code> to values larger than 100.

[/text]

简单地说vm.overcommit_memory = 0,这时候可以申请到比较多的内存,但是仍然会在一定的时候申请失败;vm.overcommit_memory = 1,所有的malloc都会成功;

vm.overcommit_memory = 2,当前可以申请的内存大小是 overcommit_ratio*物理内存大小+sawp的大小,/proc/sys/vm/overcommit_ratio 默认值是50.这个时候/proc/sys/vm/overcommit_ratio 设置过小会浪费内存,造成一部分内存不能被使用,设置过大又失去意义。需要根据实际情况调整。

另外就是还可以根据/proc/meminfo查看当前的内存状态。

[text]

<span><code><span><code>[root@test /var/log]
#  echo m > /proc/sysrq-trigger            </code></span></code></span>

<span><code>[root@test /var/log]
# cat /proc/buddyinfo
Node 0, zone      DMA      3      2      6      4      5      1      1      2      2      2      0
Node 0, zone   Normal      0      0      1      1   2360    918    161     12      1      1      0
Node 0, zone  HighMem      0      0  17900   1254     22      0      0      1      0      0      0</code></span>

<span><code>[root@test /var/log]
# grep HighMem: /var/log/messages |tail -n 1
Jun 20 16:02:37 free-72-222 kernel: HighMem: 0*4kB 0*8kB 17948*16kB 1254*32kB 22*64kB 0*128kB 0*256kB 1*512kB 0*1024kB 0*2048kB 0*4096kB = 329216kB</code></span>

<span><code>[root@test /var/log]
# grep Normal: /var/log/messages |tail -n 1
Jun 20 16:02:37 free-72-222 kernel: Normal: 0*4kB 0*8kB 1*16kB 1*32kB 2371*64kB 918*128kB 161*256kB 12*512kB 1*1024kB 1*2048kB 0*4096kB = 319728kB</code></span>

<span><code>[root@test /var/log]
# cat /proc/meminfo
MemTotal:      4096132 kB
MemFree:        655324 kB
Buffers:        265820 kB
Cached:        2101480 kB
SwapCached:          0 kB
Active:        2690184 kB
Inactive:       595584 kB
HighTotal:     3350528 kB
HighFree:       328256 kB
LowTotal:       745604 kB
LowFree:        327068 kB
SwapTotal:           0 kB
SwapFree:            0 kB
Dirty:            1236 kB
Writeback:           0 kB
Mapped:         969720 kB
Slab:            94556 kB
CommitLimit:   2048064 kB
Committed_AS:  4843488 kB
PageTables:       4580 kB
VmallocTotal:   114680 kB
VmallocUsed:      1232 kB
VmallocChunk:   112956 kB</code></span>

[/text]

从上面可以看到/proc/meminfo里的LowFree和HighFree和buddyinfo 以及messages里打印的是相同的。

另外我们也能看到buffer和cache占用了大量的内存,会不会是某些进程频繁地malloc+free,系统来不及回收造成了最后的OOM?有个参数/proc/sys/vm/drop_caches 可以调整

内核对buffer和caches的处理:

[text]

Writing to this will cause the kernel to drop clean caches, dentries and
inodes from memory, causing that memory to become free.

To free pagecache:
echo 1 > /proc/sys/vm/drop_caches
To free dentries and inodes:
echo 2 > /proc/sys/vm/drop_caches
To free pagecache, dentries and inodes:
echo 3 > /proc/sys/vm/drop_caches

As this is a non-destructive operation and dirty objects are not freeable, the
user should run `sync' first.</code></span></span></span>

[/text]

执行sync同步后可以试试echo 3 > /proc/sys/vm/drop_caches把buffer和cache都释放出来,不过实际上感觉这样也是治标不治本。还是得从应用这个源头去找原因。最后查出来时jvm的参数设置的有问题,机器的内存就2G,但是jvm堆栈内存设置的过大,所以导致多次的OOM。另外还有此查出来是自动挂载NFS的automount有bug,导致产生了巨多的网络链接,没有办法只有重启机器,重启后就OK了。

此条目发表在System分类目录。将固定链接加入收藏夹。

发表评论