dun*_*nxd 41 linux web-server memory-usage linux-kernel
由于 oom-killer 启动,我的 VPS Web 服务器在 CentOS 5.4(Linux 内核 2.6.16.33-xenU)上不规则地运行(例如每月一次或需要几周)变得无响应。服务器的监控表明它没有通常用完内存,只是每隔一段时间。
我已经阅读了一些指向此页面的博客,其中讨论了使用以下 sysctl 设置来配置内核以更好地管理过度使用:
vm.overcommit_memory = 2
vm.overcommit_ratio = 80
Run Code Online (Sandbox Code Playgroud)
我对此的理解(这可能是错误的,但我找不到一个规范的定义来澄清)是,这可以防止内核过度分配超出交换区 + 80% 物理内存的内存。
但是,我还阅读了一些其他来源,表明这些设置不是一个好主意 - 尽管这种方法的批评者似乎在说“不要做破坏您的系统的事情,而不是尝试这种混乱”的假设因果关系总是已知的。
所以我的问题是,在托管大约 10 个低流量站点的 Apache2 Web 服务器的上下文中,这种方法的优缺点是什么?在我的特定情况下,Web 服务器有 512Mb RAM,1024Mb 交换空间。大多数情况下,这似乎已经足够了。
phe*_*mer 35
设置overcommit_ratio
为 80 可能不是正确的操作。将该值设置为小于 100 的任何值几乎总是不正确的。
这样做的原因是 linux 应用程序分配的比它们真正需要的多。假设他们分配了 8kb 来存储几个文本字符串。嗯,那里有几个 KB 未使用。应用程序经常这样做,这就是过度使用的目的。
因此,基本上在 100 时过量使用时,内核将不允许应用程序分配比您拥有的内存(交换 + ram)更多的内存。将其设置为小于 100 意味着您将永远不会使用所有内存。如果您要设置此设置,则应将其设置为高于 100,因为上述场景非常常见。
然而,虽然将其设置为大于 100 几乎总是正确的答案,但在某些用例中将其设置为小于 100 是正确的。如前所述,这样做您将无法使用所有内存。但是内核仍然可以。所以你可以有效地使用它来为内核保留一些内存(例如页面缓存)。
现在,至于您的 OOM 杀手触发问题,手动设置过量使用不太可能解决此问题。默认设置(启发式确定)相当智能。
如果您想看看这是否真的是问题的原因,请查看/proc/meminfo
OOM 杀手何时运行。如果您看到Committed_AS
接近CommitLimit
,但free
仍然显示可用内存,那么您可以为您的方案手动调整过量使用。将此值设置得太低将导致 OOM 杀手在您仍有大量可用内存时开始杀死应用程序。将它设置得太高会导致随机应用程序在尝试使用分配的内存时死亡,但实际上并不可用(当所有内存实际上都用完时)。
Ale*_*eys 25
@dunxd 提到的文档中的第 9.6 节“过度使用和 OOM”特别生动地说明了允许过度使用的危险。然而,这80
对我来说也很有趣,所以我进行了一些测试。
我发现这overcommit_ratio
会影响所有进程可用的总 RAM。根进程似乎与普通用户进程没有区别对待。
将比率设置为100
或更少应该提供经典语义,其中返回值malloc/sbrk
是可靠的。将其比率设置为低于100
可能是为非进程活动(如缓存等)保留更多 RAM 的一种方式。
因此,在我的计算机上,内存为 24 GiB,禁用交换,使用 9 GiB,top
显示
Mem: 24683652k total, 9207532k used, 15476120k free, 19668k buffers
Swap: 0k total, 0k used, 0k free, 241804k cached
Run Code Online (Sandbox Code Playgroud)
以下是一些overcommit_ratio
设置以及我的 ram-consumer 程序可以获取多少 RAM(触摸每个页面) - 在每种情况下,程序一旦malloc
失败就会干净利落地退出。
50 ~680 MiB
60 ~2900 MiB
70 ~5200 MiB
100 ~12000 MiB
Run Code Online (Sandbox Code Playgroud)
一次运行几个,即使有些人是 root 用户,也不会改变他们一起消耗的总量。有趣的是,它无法消耗最后 3+ GiB 左右;在free
没降远低于此处显示的:
Mem: 24683652k total, 20968212k used, 3715440k free, 20828k buffers
Run Code Online (Sandbox Code Playgroud)
实验很混乱 - 在所有 RAM 都在使用的时候使用 malloc 的任何东西都倾向于崩溃,因为许多程序员对检查 C 中的 malloc 失败很糟糕,一些流行的集合库完全忽略它,而 C++ 和其他各种语言甚至更差。
大多数虚RAM我看到的早期实现的是处理一个非常特殊的情况下,在一个大的过程-比如可用内存的51%+ -需要fork()
以exec()
一定的支持程序,通常是一个非常非常小的一个。具有写时复制语义的操作系统将允许fork()
,但附带条件是,如果分叉进程实际上尝试修改太多内存页面(然后每个内存页面都必须实例化为独立于初始巨大进程的新页面)它最终会被杀死。父进程只有在分配更多内存时才会处于危险之中,并且可以处理耗尽,在某些情况下,只需等待一些其他进程死亡,然后继续。子进程通常只是通过一个(通常较小的)程序替换自己exec()
然后就没有附带条件了。
Linux 的过度使用概念是一种极端的方法,既允许fork()
发生,也允许单个进程大规模过度分配。OOM杀手造成的死亡人数是异步的,甚至到节目做处理内存分配负责任。我个人总体上讨厌系统范围的过度使用,尤其是 oom-killer - 它促进了一种恶魔般的内存管理方法,这种方法会感染库并通过它们感染使用它们的每个应用程序。
我建议将比率设置为 100,并且也有一个交换分区,这通常只会被大型进程使用 - 通常只使用自己被塞入交换的部分的一小部分,因此保护绝大多数进程免受 OOM 杀手错误功能的影响。这应该可以使您的网络服务器免受随机死亡的影响,并且如果它被编写为malloc
负责任地处理,甚至可以避免自杀(但不要押注后者)。
这意味着我正在使用它 /etc/sysctl.d/10-no-overcommit.conf
vm.overcommit_memory = 2
vm.overcommit_ratio = 100
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
51941 次 |
最近记录: |