http://www.vpsee.com/2013/10/how-to-configure-the-linux-oom-killer/
http://www.cnblogs.com/itfriend/archive/2011/12/14/2287160.html
其他可选的临时解决方法:
关闭oom-killer
echo "0" > /proc/sys/vm/oom-kill
vi /etc/sysctl.conf
vm.oom-kill = 0
2. 清空cache (可选)
echo 1 > /proc/sys/vm/drop_caches
之前做游戏时遇到一次 OOM killer。细节有些忘记了。和这个差不过。就保存下来了。、
转自 http://www.kuqin.com/linux/20120701/321430.html
受害人口述悲惨的遭遇——
1、最近一段时间(更换了预发机器后)我负责的一个应用的预发环境(线上稳定得像个婴儿~)特别不稳定,最先是应用频频的过几天就发现提供的接口不工作了,但容器Jetty还在跑得欢,于是jstack/jmap看,发现没有一个线程在跑我的war包中的程序,但是容器里个中间件的sar还跑得很欢(-_-|||),dump出来的对象也没有一点蛛丝马迹,所有日志到04:03就什么也没有了。然后查发现一个中间件的sar(远程接口层)包刚好在那个时候升级了,这玩意用OSGI的CloassLoader来加载整个应用,自然就怀疑它怎么着把我的Class都卸载掉了。简单,回滚到前一版本试试。
2、诡异的第二天还是4:03分,又发作了!排除了新sar的原因,就百思不和其解了,发现-XX:+CMSClassUnloadingEnabled开着,关掉。第二天还是一样!各种看代码都没有问题,在一个无穷循环的线程里打日志,各种招都用上还是老样子,连Servlet消失了,突然对哥掌握的Java知识产生了莫名其妙的怀疑…
3、这个应用改过名字,上边2个应用的目录都存在的。发现老目录的log文件修改时间居然是当前时间,再PS一看,发现启的进程是老应用的!新老2个war变化非常大,之前验证的点在老war里都木有的,好,觉得终于找着原因了。删老目录,找PE查脚本,果然查到启老应用的脚本!停掉脚本。甚至把老的应用目录link到新应用,即使脚本改不干净也不致于把我应用杀掉,免受接口调用方骚扰啊。
4、奇迹再一次发生了。应用在4:03准时消失了,老的确实也不起来了。
因为是预发环境,线上完全无问题,怀疑是环境问题所以也就一直没花太多时间去查。PE也觉不再有脚本在跑了,好吧,决定好好查一下。
首先,看系统日志,希望能找到SSH登录日志、命令执行日志或进程启动/终止日志,搜4点这个时间,wtmp/secure都没有发现。
然后,找messages这个时间点,找到:
Jun 20 04:05:14 ***.pre.cm3 kernel: : java invoked oom-killer: gfp_mask=0x201d2, order=0, oomkilladj=0
Jun 20 04:05:14 ***.pre.cm3 kernel: :
Jun 20 04:05:14 ***.pre.cm3 kernel: : Call Trace:
Jun 20 04:05:14 ***.pre.cm3 kernel: : [] out_of_memory+0x8b/0x203
...
Jun 20 04:05:18 ***.pre.cm3 kernel: : Mem-info:
...
oom-killer,之前不知道有这个东西,想想JVM自己不可能发生OOM,因为即没OOM日志也没Crash Core日志,而且还每次都是同一时间点!应用中也木有这种定时任务。
关于Linux OOM-killer机制——
linux oom-killer是一种自我保护机制,当系统分配不出内存时(触发条件)会触发这个机制,由操作系统在己有进程中挑选一个占用内存较多,回收内存收益最大的进程kill掉来释放内存。
系统为每个进程做评估(/proc/<pid>/oom_score中数值最大的进程被kill掉),参考这里。
前面的问题,Java进程占用内存足够多,进程生存又比较短,正是OOM-killer的首选啊,所以中招。
- /**
- * badness – calculate a numeric value for how bad this task has been
- * @p: task struct of which task we should calculate
- * @uptime: current uptime in seconds
- *
- * The formula used is relatively simple and documented inline in the
- * function. The main rationale is that we want to select a good task
- * to kill when we run out of memory.
- *
- * Good in this context means that:
- * 1) we lose the minimum amount of work done
- * 2) we recover a large amount of memory
- * 3) we don’t kill anything innocent of eating tons of memory
- * 4) we want to kill the minimum amount of processes (one)
- * 5) we try to kill the process the user expects us to kill, this
- * algorithm has been meticulously tuned to meet the principle
- * of least surprise … (be careful when you change it)
- */
另外,Linux的malloc分配内存,也不是一次到位的真分配了指定大小的物理内存(Overcommit机制,另一篇也不错,这里Fenny一篇),而是先承诺你,实际用到的时候才去系统分配,如果刚好那个时候内存不够了,就会触发oom-killer。
Linux下有3种Overcommit的策略(参考内核文档:vm/overcommit-accounting),可以在/proc/sys/vm/overcommit_memory配置。取0,1和2三个值,默认是0。
0:启发式策略,比较严重的Overcommit将不能得逞,比如你突然申请了128TB的内存。而轻微的Overcommit将被允许。另外,root能Overcommit的值比普通用户要稍微多些。
1:永远允许Overcommit,这种策略适合那些不能承受内存分配失败的应用,比如某些科学计算应用。
2:永远禁止Overcommit,在这个情况下,系统所能分配的内存不会超过swap+RAM*系数(/proc/sys/vm/overcmmit_ratio,默认50%,你可以调整),如果这么多资源已经用光,那么后面任何尝试申请内存的行为都会返回错误,这通常意味着此时没法运行任何新程序。
我的机器为什么会触发OOM-killer——
先查了下sar的日志:
- 12:00:01 AM CPU %user %nice %system %iowait %steal %idle
- 04:00:01 AM all 0.01 0.00 0.00 0.00 0.01 99.98
- 04:10:02 AM all 0.55 0.00 20.71 37.97 0.06 40.71
- 04:20:01 AM all 0.01 0.00 0.04 0.24 0.01 99.71
system cpu占的比较多,应该是kernel OOM-killer执行所占掉的。再看没有启java进程情况下这个时间点的日志,CPU是正常的。
cat /proc/sys/vm/overcommit_memory 值0,即启发式策略,允许Overcommit。
再看这台机器上比较消耗内存的进程:
总可用内存才2G(更换机器之前为4G,后面的配置是按4G来配的),JVM就申请了2G+,再加上nginx所占申请内存,远超实际物理内存2G+Swap 1G范围了,应用之所以正常是应用启动不久,实际用的内存并没用那么多,到晚上达到临界值,其实一个不相干的定时任务申请内存,刚好就触发了OOM-killer了。
nginx和java应用线上长时间验证是稳定的,不存在内存泄露,至于机器上4:03启动了什么任务,其实都不那么重要了。
参考资料:
How the Linux OOM killer works
Linux 的 Out-of-Memory (OOM) Killer
相关推荐
Linux系统的OOM Killer处理机制.docx
前面一节重点分享了Linux的内存分配策略,基于上述的分配策略,为了规避超售的风险,Linux采了一种OOM Killer的机制,即系统可用内存(包括Swap)即将使用完之前,选择性的Kill掉一些进程以求释放一些内存
heart_oom_protect 一个Erlang OTP库,可保护心脏免于被Linux内核的OOM Killer杀死 建造 $ rebar3 compile
1 概述 Android的设计理念之一,便是应用程序退出,但进程还会继续存在系统以便...Android基于Linux的系统,其实Linux有类似的内存管理策略——OOM killer,全称(Out Of Memory Killer), OOM的策略更多的是用于分配内存
oom-killer通常在Linux用户中享有不良声誉。 这可能是Linux仅在绝对没有其他选择时才调用它的部分原因。 它将换出桌面环境,删除整个页面缓存,并在最终终止进程之前清空每个缓冲区。 至少那是我认为的做法。 我坐...
OOM Killer 一般我们的linux服务都是混部服务的,每个程序申请的物理内存都是共享的;例如物理内存只有1g,启动2个程序各申请1g是可以的,linux通过这种过度分配的方式来达到内存的充分利用,当程序实际使用内存超出...
这个错误是在Master进程向子进程send消息时发现pipe已经关闭了的情况下由Master进程报出来的。 2019-12-16 14:33:02,pid-170096, Error ...经排查这个问题原因是子进程占用内存太多,触发了Linux内核的OOM Killer机制
前面两章,我们分析了Linux内存分配的策略以及Linux通过使用 OOM_Killer的机制解决了“超售”引起的风险,MySQL同其他的应用程序一样,在操作系统允许的范围内也是可以超售的,一般人理解,Innodb_buffer_pool必须...
nohang软件包为Linux提供了一个高度可配置的守护程序,该守护程序能够正确地防止(OOM)并在内存不足的情况下保持系统响应速度。 该软件包还包括其他诊断工具( oom-sort , psi2log , psi-top )。 问题是什么?...
This is a set of scripts for android that sets oom_adj value of selected processes to -17. It prevents killing this processes by oom_killer:script with list of protected processes.
不建议输入100MiB以下的内存值,否则程序可能会一直将swap空间吃完,触发malloc失败,从而可能引起系统死机、崩溃、触发oom_killer等后果。 b. 单位越大分配速度越快,精确度越低,推荐使用M(m)。 ************...