配置vm.overcommit_memory的效果


41

我的VPS Web服务器在CentOS 5.4(Linux内核2.6.16.33-xenU)上不定期运行(例如每月一次或几周一次),由于oom-killer的介入而无法响应。对服务器的监视表明它没有通常每隔一段时间就会耗尽内存。

我已经阅读了指向该页面的两个博客,讨论了如何使用以下sysctl设置配置内核以更好地管理过量使用:

vm.overcommit_memory = 2
vm.overcommit_ratio = 80

我对此的理解(这可能是错误的,但是我找不到规范的定义要澄清),这可以防止内核在交换+ 80%的物理内存之外过度分配内存。

但是,我还阅读其他一些资料,建议这些设置不是一个好主意-尽管对此方法的批评者似乎在说:“不要做任何事情来破坏您的系统,而不是尝试进行这种麻烦”,但前提是:因果关系是众所周知的。

所以我的问题是,在托管大约10个低流量站点的Apache2 Web服务器的情况下,这种方法的优缺点什么?在我的特定情况下,Web服务器具有512Mb RAM和1024Mb交换空间。在大多数情况下,这似乎是足够的。

Answers:


32

设置overcommit_ratio为80可能不是正确的操作。将该值设置为小于100几乎总是不正确的。

这样做的原因是linux应用程序分配了超出其实际需要的资源。假设他们分配8kb来存储几个文本字符串。多数民众赞成在几个KB未使用的权利。应用程序经常这样做,而这正是过量使用的目的。

因此,基本上,如果过量使用100,内核将不允许应用程序分配比您更多的内存(交换+内存)。将其设置为小于100意味着您将永远不会使用所有的内存。如果要设置此设置,由于前面提到的情况,这应该设置为高于100。

现在,对于您的OOM杀手级触发问题,手动设置过量使用将无法解决此问题。默认设置(启发式确定)非常智能。

如果您希望查看是否确实是造成此问题的原因,请查看/proc/meminfoOOM杀手的运行时间。如果您看到Committed_AS接近CommitLimit,但free仍显示可用内存可用,那么可以,您可以手动调整方案的过量使用。将此值设置得太低会导致OOM杀手在仍然有足够的可用内存时开始杀死应用程序。设置得太高会导致随机应用程序在尝试使用已分配的内存时死亡,但实际上并不可用(当所有内存确实用完时)。


1
谢谢-我正在尝试将overcommit_ratio设置为100以查看会发生什么。我的主要问题是,当oom-killer启动时,它总是会杀死sshd,从而阻止我访问服务器并查看正在发生的情况。我想我真正需要的是停止oom-killer的运行,并以某种方式记录它可能在运行时会发生的情况,以便我找出问题的原因。
dunxd 2012年

4
@dunxd可以/proc/<PID>/oom_score_adj用于此目的。例如,如果将sshd的oom_score_adj设置为-1000,则当想要杀死某对象时,oom killer永远不会将sshd作为目标。完全停止oom killer并不是一个好主意,因为这样您的程序将无法分配内存,并且它们还是会死掉。
Patrick

4
@dunxd继承了。让您的初始化脚本自行对其进行设置,由初始化脚本启动的所有内容都将继承该脚本。
Patrick

4
您的4 KB示例是错误的。虚拟内存用于页面,Linux下页面的(最小)大小为4 KB。这意味着存储两个字符需要4 KB的映射空间,而无论超负荷设置如何。内存超额分配的一个恰当示例是,例如,您分配了10 KB且仅使用前4100个字节。这意味着需要两个4 KB页面来存储数据,而另一个多余页面则未被使用。非过量使用的系统总是会在需求到达时准备好第三页来存储数据,而过量提交的系统将不会强制执行。
jlliagre

2
/ proc / self指向当前进程,因此/ proc / self / oom_score_adj可用于更改当前进程的oom_score_adj。
r_2 2014年

23

@dunxd提到的文档中的第9.6节“过量使用和OOM”特别是关于允许过量使用的危险的图形。但是,该80外观对我也很有趣,因此我进行了一些测试。

我发现这overcommit_ratio会影响所有进程可用的总RAM。根进程似乎与普通用户进程没有什么不同。

将比率设置为100或小于应该提供经典的语义,其中返回值malloc/sbrk是可靠的。将其比率设置为低于100可能为非进程活动(例如缓存等)保留更多RAM的一种方式。

因此,在我的具有24 GiB RAM的计算机上,禁用了交换功能,正在使用9 GiB,并top显示

Mem:  24683652k total,  9207532k used, 15476120k free,    19668k buffers
Swap:        0k total,        0k used,        0k free,   241804k cached

以下是一些overcommit_ratio设置以及我的ram-consumer程序可以获取多少RAM(触摸每页)-在每种情况下,一旦malloc失败,程序都会干净退出。

 50    ~680 MiB
 60   ~2900 MiB
 70   ~5200 MiB
100  ~12000 MiB

一次运行多个,即使以root用户身份运行一个,也不会改变他们一起消耗的总金额。有趣的是,它无法消耗最近的3+ GiB左右。在free没降远低于此处显示的:

Mem:  24683652k total, 20968212k used,  3715440k free,    20828k buffers

实验是混乱的-由于所有程序员都非常担心在C中检查malloc失败,因此在使用所有RAM时立即使用malloc的任何事情都会崩溃,一些流行的集合库完全忽略了它,甚至C ++和其他各种语言也是如此。更差。

我看到的虚构RAM的大多数早期实现都是处理一个非常特殊的情况,在这种情况下,fork()为了exec()支持某个程序,通常需要一个大得多的程序,例如一个可用内存的51%以上。具有写时复制语义的OS允许使用fork(),但附带条件是,如果分叉的进程实际上试图修改太多的内存页面(然后必须将每个内存页面实例化为独立于初始大型进程的新页面)最终会被杀死。父进程只有在分配更多内存时才处于危险之中,并且可以处理耗尽,在某些情况下,只需稍等一些其他进程终止,然后继续运行即可。子进程通常通过以下方式(通常是较小的)程序代替自身:exec() 然后摆脱了附带条件

Linux的过量使用概念是一种极端的方法,它既可以使之fork()同时发生,也可以使单个进程得以大规模整合。由OOM杀手引起的死亡异步发生,即使是确实负责地处理内存分配的程序也是如此。我个人讨厌整个系统的过度使用,尤其是oom-killer-它在内存管理中采用了一种“恶魔般贴心”的方法,这种方法会感染库以及使用它们的每个应用程序。

我建议将比率​​设置为100,并且还要有一个交换分区,它通常只会最终被大型进程使用-这些进程通常只使用自身一部分的很小一部分,从而塞入交换中,因此保护大多数进程免受OOM杀手功能的影响。这应该可以保护您的Web服务器免遭随机死亡的威胁,并且如果它被编写为malloc负责任地处理,甚至可以防止其自杀(但不要押注后者)。

那意味着我在用这个 /etc/sysctl.d/10-no-overcommit.conf

vm.overcommit_memory = 2
vm.overcommit_ratio = 100

并且您是否建议将vm.overcommit_memory保持为2?
Ut xD 2015年

1
注意-这确实是我正在使用的;我想我在回答中省略了它,因为它已经存在问题了
Alex North-Keys
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.