我手上有一台 2 核 1.8G 内存的 ECS,跑着 nginx、Node.js、Python 服务,外加 Hexo 博客和每天自动写文章的 Agent。最初我总担心它随时会 OOM 崩掉——1.8G,连现在一个 Chrome 标签页都喂不饱。
但实际上,它已经稳稳跑了几个月,没出过事。这篇就把压箱底的优化策略摊开说说。
第 1 招:Swap 不是万能的,但没有 Swap 是万万不能的
物理内存不够用,Swap 就是你的兜底。但很多人对 Swap 有误解——觉得它慢、伤磁盘,干脆关掉。这是把洗澡水和孩子一起倒掉了。
关键配置:把 swappiness 调到合适的值。
1 | # 查看当前值 |
swappiness=60 意味着当内存还剩 40% 空闲时,内核就可能开始交换。对低配机器来说,这太激进了——你会看到明明还有几百兆内存,系统却在用 swap。降到 10 之后,只有物理内存真正吃紧时才会换页。
Swap 文件 vs Swap 分区:
个人建议用 swap 文件。ECS 云盘分区分好了再改很麻烦,而 swap 文件只是一个文件,随时可以调整大小:
1 | # 创建 2G swap 文件 |
2G swap + 1.8G 物理内存,约等于有了接近 4G 的可用空间。
第 2 招:找到内存黑洞,一个都别放过
光有 swap 不够,得知道谁在吃内存。
1 | # 按内存使用排序,只看前 10 |
但我更推荐这个一行命令:
1 | ps -eo pid,ppid,cmd,%mem,%cpu,rss --sort=-%mem | head -20 | \ |
定期 watch -n 60 'ps aux --sort=-%mem | head -11' 能帮你建立对服务器的直觉。我就是在这样看了几天后,发现某个 Node.js 服务的内存 leak 了——每次请求涨 2MB,48 小时后吞掉 500M。
解决方案:加了个 systemd 服务的 MemoryMax 限制:
1 | [Service] |
超出 400M 会慢下来,超出 500M 直接 OOM kill。配上 systemd 的自动重启,服务挂了也能秒复活。
1 | Restart=on-failure |
第 3 招:nginx 的节俭调优
nginx 本身已经很轻量了,但默认配置是为通用场景优化的,低配机器可以再榨一榨:
1 | # /etc/nginx/nginx.conf |
静态文件缓存也要开:
1 | location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { |
Hexo 生成的静态文件全是 hash 命名的,immutable 让浏览器放心缓存,再也不回源请求。
第 4 招:Node.js 的——不,先别急着上 PM2
很多人启动 Node 服务第一件事就是 npm i -g pm2。但低配机器上 PM2 本身就要占 30-50MB 内存。如果只是一个简单的服务,用 systemd 就够了:
1 | [Unit] |
没有 PM2 的守护进程、日志进程、监控进程,一个 node 进程干干净净。
如果实在需要进程管理,我推荐用 standalone 模式的 PM2——只开一个进程,不 fork 出守护进程:
1 | pm2 start app.js --no-daemon |
第 5 招:定时释放 + 主动预警
光防 OOM 还不够,得在出事前知道。
我们服务器上跑着一个 10 分钟的监控脚本,检查内存和磁盘情况。用的就是纯 shell:
1 |
|
搭配 cron 每 10 分钟跑一次,没问题就静默,有问题才推送——这种「静默即平安」的模式,比每天去看监控面板省心多了。
第 6 招:最被低估的优化——什么都不做
现代 Linux 内核的内存管理比你想象的聪明。只要不是真正的内存泄漏,很多时候「看着占了很多内存」其实是 page cache——内核用空闲内存来缓存文件 I/O,需要时会自动释放。
1 | # 这一行告诉你真正的内存状况 |
注意看 available 这一列,它才是真正可用的内存(包括可以随时回收的 cache)。used 那一列高不可怕,available 低才要慌。
1 | # 别手贱去清 cache |
除非你要跑内存基准测试,否则别碰这条命令。内核自己管理得很好,你清掉 cache 只会让下次读取变慢。
写在最后
低配服务器就像在螺蛳壳里做道场——空间有限,但也逼你学会珍惜每一点资源。用好 swap + systemd 限制 + 合理配置 + 静默监控,1.8G 内存也能跑出从容。
其实大部分个人项目和小博客,高峰期也就几十个并发,2GB 绰绰有余。瓶颈从来不是资源,而是资源被浪费的方式。
最后送大家一句 Thomas 的台词——“The needs of the many outweigh the needs of the few.” 把内存留给真正需要的进程,让 cache 去做 cache 该做的事,你的小服务器会比你以为的坚强得多。