最近维护测试服务器越来越多出现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,当前可以申请的内存大小是
默认值是50.这个时候
设置过小会浪费内存,造成一部分内存不能被使用,设置过大又失去意义。需要根据实际情况调整。
[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]
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]
<span><span><span><code>执行sync同步后可以试试echo 3 > /proc/sys/vm/drop_caches把buffer和cache都释放出来,不过实际上感觉这样也是治标不治本。还是得从应用这个源头去找原因。最后查出来时jvm的参数设置的有问题,机器的内存就2G,但是jvm堆栈内存设置的过大,所以导致多次的OOM。另外还有此查出来是自动挂载NFS的automount有bug,导致产生了巨多的网络链接,没有办法只有重启机器,重启后就OK了。