为什么Linux在使用大量内存时会变得无响应(无法触发OOM)

为什么Linux在使用大量内存时会变得无响应(无法触发OOM)

我在 AWS 中使用 CentOS 7.5 实例,它有 16 个 CPU 和 32GB 内存。我发现当我运行以下命令时,整个系统将没有响应,我无法再在其上运行任何命令,甚至无法建立新的 SSH 会话(但仍然可以 ping 它)。而且我根本没有看到 OOM 杀手被触发,似乎整个系统永远挂起。

stress --vm 1 --vm-bytes 29800M --vm-hang 0 

但是,如果我运行stress --vm 1 --vm-bytes 29850M --vm-hang 0消耗更多内存(50MB),OOM Kill 将被成功触发(我可以在 中看到它dmesg)。如果我运行stress命令消耗的内存少于 29800MB(例如stress --vm 1 --vm-bytes 29700M --vm-hang 0),系统将做出响应(并且不会出现 OOM 终止),并且我可以像往常一样运行任何命令。

因此,对于这个实例来说,这似乎29800MB是一个“幻数”,如果我运行stress命令来使用比它更多的内存,该命令将被 OOM 终止,如果我运行stress命令来使用比它更少的内存,那么一切都正常,如果我运行stress命令只使用29800MB内存,整个系统就会无响应。我还在具有不同规格的 Linux 主机中观察到相同的行为,例如在具有 72 个 CPU 和 144GB 内存的 CentOS 7.5 实例中,“幻数”是“137600MB”。

我的问题是,为什么使用内存的“幻数”时不会触发 OOM Kill ?

答案1

哦,这个话题已经讨论过了。

看:

Linux 内核无法优雅地处理低内存压力

让我们来谈谈房间里的大象——Linux 内核无法优雅地处理低内存压力

解决方案?各种守护进程,例如早间(在 Fedora 32 中默认安装并启用)这是我的最爱。还有其他的:

答案2

问题的根本原因是,只有在尝试运行所有进程时无法取得任何进展时,OOM Killer 才会被激活。请注意,“向前进度”被认为是一些内存可以连续可用,其中“连续”是在扫描整个虚拟内存页表结构一次后至少有 4 KB 的更多 RAM。

最坏的情况行为需要持续扫描该结构很长时间,以至于系统看起来挂起,因为这个过程没有时间限制,只要内存子系统可以向前推进,它就会尝试继续前进,尽管速度非常慢。扫描整个内存可能需要长达 0.5 秒的时间,最坏情况下前进进度会导致 4 KB 可用内存。如果系统实际上需要 20 MB 来重新渲染显示,则需要对内存进行大约 2500 次扫描才能成功,并且需要半个多小时。显然,一个屏幕刷新需要半个小时的系统对于用户来说相当于完全挂起的系统,即使内核对此进度感到满意。

我认为最好的选择是允许指定内存子系统的最大延迟,并且当延迟太高时,OOM Killer 会自动激活(例如,内存管理子系统必须能够提供至少 100 MB 每秒的可用空间,或者系统状态应该被视为 RAM 不足)。或其他类似解决方案的问题earlyoom在于,为了避免高峰值负载的最坏情况行为,这些解决方案需要非常宽的安全裕度,这会使您为了安全裕度而浪费 RAM。

相关内容