关键词:OOM、Swap、Linux 内存、2核2G 服务器、运维复盘
结论先行:Swap 不是性能方案,但在 OOM 面前,它是救命绳。


一、事故背景

我有一台 2核2G 的云服务器,主要用途是运行一个博客网站:

  • Halo(Spring Boot)

  • MySQL

  • Nginx

访问量不算高,但有一天开始,网站出现了非常诡异的情况:

  • 页面偶尔打不开

  • 服务会“莫名其妙”重启

  • 日志里没有明显报错

  • 重启服务器后短暂恢复,过一会儿问题再次出现

一开始我以为是程序 Bug,直到我第一次真正看懂了 OOM


二、什么是 OOM?我当时是怎么“被它教育”的

OOM,全称 Out Of Memory,意思是:

系统内存耗尽,Linux 内核为了自保,强制杀死某个进程。

关键点在于:
被杀的进程通常不会给你任何体面的告别。

对我来说,表现就是:

  • Java 进程突然消失

  • 网站直接 502

  • 没有 Java 异常栈

  • 只有系统日志里一句冷冰冰的:

    Out of memory: Kill process xxxx (java)
    

那一刻我才意识到:
不是程序挂了,是系统扛不住了。


三、为什么 2核2G 服务器这么容易 OOM?

问题并不复杂,但非常常见。

1. Java 默认配置是“无上限”的

在没有明确设置 -Xmx 的情况下:

  • JVM 会根据系统内存自动扩展堆

  • 在小内存服务器上,这几乎等于“放飞自我”


2. 系统内存不是只给 Java 用的

同一台机器上,还有:

  • MySQL

  • Linux 内核

  • 文件缓存(page cache)

  • 其他守护进程

当这些同时争抢内存时,OOM 是迟早的事


3. 没有 Swap,系统连“缓冲区”都没有

当时我服务器的状态是:

  • 内存快满

  • Swap = 0

  • 一旦有内存峰值,系统没有任何缓冲空间

👉 结果就是:OOM Killer 直接出手。


四、我做的第一件正确的事:创建 Swap 分区

在明确问题根源后,我做的第一件事不是“重装系统”,而是:

给服务器加一块 Swap。


Step 1:创建 2GB Swap 文件

fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile

并写入 /etc/fstab,保证重启后生效:

/swapfile none swap sw 0 0

Step 2:调整 swappiness(非常关键)

echo 'vm.swappiness=10' | tee /etc/sysctl.d/99-swappiness.conf
sysctl -p /etc/sysctl.d/99-swappiness.conf

这一步的意义是:

  • 平时尽量不用 swap

  • 只有内存快撑不住时才用


五、Swap 生效后,发生了什么变化?

1. OOM 消失了

这是最直接的变化:

  • Java 不再被系统杀死

  • 网站不再“莫名其妙”挂掉


2. 系统行为变得“温和”

通过 free -h 我看到:

  • swap 偶尔使用几十 MB

  • 内存峰值被“削平”

  • CPU 抖动明显减少

这说明:

Swap 成功扮演了“缓冲带”的角色。


六、我后来才明白的一件事:Swap 不是解决方案本身

非常重要的一点:

Swap 不能替代内存,它只是延迟死亡。

如果只是“加 swap”,而不做任何优化:

  • 程序还是会慢

  • IO 会变多

  • 最终仍然可能崩

所以,在启用 Swap 之后,我还做了这些事:

  • 限制 JVM 最大内存

  • 压缩 MySQL Buffer Pool

  • 删除不必要的插件

Swap 只是第一道防线,不是终点。


七、什么时候应该用 Swap?什么时候不该?

✅ 适合用 Swap 的场景

  • 小内存服务器(1–4GB)

  • Java / Node / Python 服务

  • 内存偶发峰值

  • 希望避免 OOM


❌ 不该依赖 Swap 的场景

  • 长期高负载

  • swap 使用量持续增长

  • 页面明显变慢

这时候,正确的选择是:

优化配置,或者加内存。


八、这次事故带给我的三个教训

  1. OOM 往往不是程序 Bug,而是资源边界失控

  2. Swap 是服务器的安全气囊,不是发动机

  3. 默认配置在小服务器上,几乎一定是错的


结语

这次 OOM 事故让我真正理解了一件事:

服务器不是“挂了”,
而是在用最极端的方式提醒你:
你超出了它的能力边界。

Swap 让我有机会从事故中活下来
而真正让我系统稳定下来的,是后续对内存的尊重。