Linux系统 OOM Killer(Out Of Memory killer)问题排查

原创
2016/05/20 16:05
阅读数 4.1K

1) Kernel真的内存耗尽了./proc/meminfo中的SwapFree和MemFree很低.都小于1%,那么负载过大就是原因.

2) 如果LowFree很低而HighFree高很多,那么就是32位体系结构的原因,如果在64位内核或平台上就会好很多.

3) 内核数据结构或者内存泄漏.

/proc/slabinfo占用最多空间的对象是什么对象?awk '{printf "%5d MB %s\n", $3*$4/(1024*1024), $1}' < /proc/slabinfo | sort -n,
如果一种对象占用了系统的大部分内存,那么就有可能是这个对象的原因.检查这个对象的子系统.

SwapFree和MemFree的大小?

task_struct对象的数字是多少?是否是因为系统fork了太多进程导致的.

4)内核没有正确使用swap分区.

如果应用程序使用了mlock()或者Huge TLBfs pages,那么有可能这个应用程序就不能使用swap空间.这种情况下,Swap Free很高仍然会OOM.mlock和Huge TLBfs pages这两个特征不允许系统将使用的内存换出,因此,这样过度使用内存会使得系统内存耗尽而让系统没有其他资源.

也有可能是系统自己有死锁.将数据写入磁盘也需要为各种各样的IP数据结构开辟内存.如果系统根本找不到这样的内存,正是用来产生空闲内存的函数会导致系统内存耗尽.可以使用一些小的调节方法比如较早的页映射机智,但是如果系统不能快速的将脏页面换出来释放内存,我们只能说负载过大而没有办法解决.增加/proc/sys/vm/min_free_kbytes会使得系统回收内存更早.这也会使得系统更难进入死锁.如果你的系统时因为死锁而导致OOM那么这是一个很好的调节值.

5)内核作出了错误的决定,读数据错误.当它还有很大RAM的时候就OOM了.

6)一些病理性的事情发生了.当内核花了一段很长的时间去扫描内存来释放.2.6.19版本的内核中,这个很长的时间指的就是VM扫描了和同一区域的active+inactive 页面6倍长的时间后.

如果内核正在快速扫描页,而你的IO设备(swap,filesystem,network fs)太慢了,内核会断定没有进程在进行交换而触发一次OOM即使swap有空闲.

解决方法:

1

2

3

DMA     0~16M

LowMem  16M~896M

HighMem 896M~

lowMem也叫Normal Zone区,是固定不能变的,如果lowMem里存在很多碎片会触发OOM killer.

察看目前系统的LowMem使用状况:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

# egrep 'Low|High' /proc/meminfo

HighTotal: 6422400 kB

HighFree: 4712 kB

LowTotal: 1887416 kB

LowFree: 307404 kB

 

# cat /proc/buddyinfo

Node 0, zone DMA 3 4 4 3 2 2 2 1 0 1 3

Node 0, zone Normal 625 586 2210 1331 953 584 123 17 1 0 2

Node 0, zone HighMem 664 15 5 2 4 2 1 2 0 0 0

 

# free -lm

total used free shared buffers cached

Mem: 8115 7849 265 0 59 5132

Low: 1843 1582 260

High: 6271 6267 4

-/+ buffers/cache: 2657 5457

Swap: 0 0 0

可以使用的解决方案:

a 添加swap分区。

b 升级64位系统

c 如果必须使用32位系统,可以使用hugemem内核,此时内核会以不同的方式分割low/high memory,而大多情况提供足够多的low memory至high memory的映射。

d 将/proc/sys/vm/lower_zone_protection的值设为250或更大。或者修改/etc/sysctl.conf vm.lower_zone_protection这将会使内核在能够在high memory中分配内存时,不会再low zone里面开辟.

e 关掉 oom-kill echo "0" > /proc/sys/vm/oom-kill 或者修改:/etc/sysctl.conf vm.oom-kill = 0 (此方法不建议,系统会变得更糟糕)

f 增大内存

g 保护单个进程 echo -17 > /proc/[pid]/oom_adj

 

 

-------------------以上盗自http://iblog.daobidao.com/linux-linux-system-oom-killer-out-of-memory-killer-approach.DaoBiDao---------------------------------------------------------------------------

然而我遇到的问题是:

tail -n 2 /var/log/message

显示的结果:

May 19 23:33:08 iZ2879ng6hoZ kernel: Out of memory: Kill process 2339 (java) score 134 or sacrifice child
May 19 23:33:08 iZ2879ng6hoZ kernel: Killed process 2339, UID 0, (java) total-vm:3248664kB, anon-rss:314076kB, file-rss:280kB
 

-------------------以下盗自http://it.deepinmind.com/java/2014/06/12/out-of-memory-kill-process-or-sacrifice-child.html--------------------------------------------------------

很明显我们被Linux内核给坑了。你知道的,Linux里面有许多邪恶的怪物(也叫作守护进程)。这些守护进程是由几个内核作业所看管的,其中的一个犹为恶毒。所有的现代Linux内核中都会有一个内存不足终结者(Out of memory Killer, OOM Killer)的内建机制,在内存过低的情况下,它会杀掉你的进程。当探测到这一情况时,这个终结者会被激活,然后挑选出一个进程去终结掉。选择目标进程使用的是一套启发式算法,它会计算所有进程的分数,然后选出那个分数最低的进程。

理解”Out of memory killer“

默认情况下,Linux内核会允许进程请求的内存超出实际可用内存的大小。这在现实世界中是有意义的,因为大多数进程其实并不会用到所有分配给它的内存(注:同一时间内不会全用到)。和这个问题最类似的就是运营商了。他们承诺卖给用户的都是100Mb的带宽,这实际上远远超出了他们的网络容量。他们赌的就是用户实际上并不会同时用完分配给他们的下载上限。一个10Gb的连接可以很轻松地承载100个以上的用户,这里的100是通过简单的数学运算得出的(10G/100M)。

这个做法的一个很明显的副作用就是,万一有一个程序正走上了一条耗尽内存的不归路怎么办。这会导致低可用内存的情况,也就是没有内存页能够再分配给进程了。你可能也碰到过这种情况,没有root帐户你是杀不掉这种顽固的进程的。为了解决这一情况,终结者被激活了,并找出了要终结的进程。

关于"Out of memory killer"参数的调整,可以参考下这篇文章

=========================================================================

机器情况:2g内存同时有运行tomcat网站也有php的论坛和博客,数据库也搭在同一台服务器(穷啊)

运行情况:通过查进程发现有大量的php-fpm进程在运行,然而并没有这么多访问。查看php-fpm配置发现启动就有大量的进程 占用很多内存

解决方案:修改php-fpm配置归还内存空间

展开阅读全文
打赏
2
3 收藏
分享
加载中
更多评论
打赏
0 评论
3 收藏
2
分享
返回顶部
顶部