如同这个问题,我们有一台具有 96GB RAM 的计算服务器,用于并行运行大型作业。
有时,物理 RAM 总量会超出,导致服务器无响应,并强制重新启动。对我来说,这是不可接受的行为,所以我正在寻找修复此问题的方法。
我知道一种方法是使用“ulimit -v”设置限制。但是,如果可能的话,我想避免采用这种方法,因为我可能偶尔会有一个非常大的进程(而不是许多小进程),因此设置有用的阈值会很困难。
我怀疑问题可能出在系统有 20GB 的交换空间:系统不会终止有问题的进程,而是会在磁盘上分配内存,这会导致系统无响应。减少交换空间量是个好主意吗?
非常感谢您对类似问题的见解或经验!
编辑
我使用以下泄漏的 C++ 程序做了一些实验:
#include <vector>
#include <unistd.h>
using namespace std;
int main(int argc,char * argv[])
{
while(true) {
vector<double>* a = new vector<double>(50000000);
sleep(1);
}
}
我第一次使用 256MB 交换文件运行它。系统完全挂起约 5 分钟,然后恢复正常。在日志中,我看到 OOM 杀手已成功杀死我的泄漏程序。
我第二次运行它时没有使用交换。这一次,机器至少十分钟没有恢复,这时我重新启动了机器。这让我很惊讶,因为我预计 OOM 杀手会在没有交换的机器上更早启动。
我不明白的是:为什么 Linux 要等到系统完全挂起后才对有问题的进程采取措施? 期望操作系统不被一个编码错误的进程完全杀死是不是太过分了?
答案1
如果你希望你的服务器仍然响应迅速,你需要尽力避免交换。但是,减少交换量或禁用它并不能解决你的问题。
您要么需要控制作业的内存使用量,要么在服务器机器上安装更多的内存。
你可以试试cgroups(控制组)来控制您的进程的 CPU 和内存使用情况。
答案2
您是否有 /var/log/messages 中的 oom 日志?
我建议检查/proc/meminfo
并在高峰使用时间对其进行监控。Committed_AS 参数显示如果内核允许所有进程同时发出所有内存请求,则需要多少内存。如果该值低于可用内存,则系统最终可能会出现 OOM。
一如既往,让工作负载适应硬件所能承受的范围。最好是增加 RAM 或减少工作负载。