PHP-FPM 被 OOM Killer 殺掉?完整排查與修復實戰紀錄(Ubuntu 16GB RAM 環境)
最近我的伺服器突然出現網站 502 錯誤,檢查後發現 php8.2-fpm 服務竟然被系統強制終止。透過一系列排查,最終確認是 Linux OOM Killer(Out Of Memory) 觸發導致。
這篇文章整理完整排查過程與解決方案,提供給遇到相同問題的人參考。
📌 問題現象
使用 systemctl status php8.2-fpm 發現:
Active: failed (Result: oom-kill)
進一步檢查 kernel log:
Out of memory: Killed process 7057 (php-fpm8.2) anon-rss:283560kB shmem-rss:119848kB
代表:
- 系統記憶體耗盡
- Linux 啟動 OOM Killer
- 強制殺掉 php-fpm worker
🔍 進一步分析
查看當時 PHP worker 記憶體使用情況:
ps -o pid,rss,etime,cmd -C php-fpm8.2 --sort=-rss | head -n 20
當時結果顯示:
RSS 約 250MB ~ 325MB/每個 worker
而之前狀態顯示:
Processes active: 80 idle: 0
🔥 問題核心
如果每個 worker 約 300MB:
300MB × 80 = 24GB
但機器只有:
15GB RAM 0GB Swap
👉 記憶體一定會爆。
🧠 伺服器環境
Memory: 15GiB Swap: 0
這代表:
- 沒有 swap 作為緩衝
- 一旦瞬間記憶體尖峰,直接 OOM
🛠 解決方案
✅ 1️⃣ 建立 8GB Swap(防止再次 OOM)
sudo fallocate -l 8G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
確認:
swapon --show free -h
結果:
Swap: 8.0GiB
建議調整 swappiness
echo 'vm.swappiness=10' | sudo tee /etc/sysctl.d/99-swappiness.conf sudo sysctl -p /etc/sysctl.d/99-swappiness.conf
✅ 2️⃣ 調整 PHP-FPM 設定(關鍵)
編輯:
/etc/php/8.2/fpm/pool.d/www.conf
修改為:
pm = dynamic pm.max_children = 25 pm.start_servers = 6 pm.min_spare_servers = 4 pm.max_spare_servers = 10 pm.max_requests = 500
為什麼設 25?
假設每個 worker 約 150MB:
150MB × 25 ≈ 3.7GB
在 15GB RAM 環境下非常安全。
✅ 3️⃣ 開啟 Slow Log(抓出慢請求)
在 www.conf 加入:
request_slowlog_timeout = 10s slowlog = /var/log/php8.2-fpm/www-slow.log request_terminate_timeout = 60s
建立目錄:
sudo mkdir -p /var/log/php8.2-fpm sudo chown -R www-data:www-data /var/log/php8.2-fpm sudo systemctl restart php8.2-fpm
查看慢請求:
sudo tail -f /var/log/php8.2-fpm/www-slow.log
📊 調整後效果
重啟後查看:
ps -o pid,rss,etime,cmd -C php-fpm8.2 --sort=-rss | head -n 20
結果:
RSS 約 100MB ~ 170MB ELAPSED 僅 20 秒左右
✔ 不再出現 300MB 以上肥 worker
✔ 不再出現 active 80
✔ 系統穩定運作
🎯 問題總結
本次 OOM 原因:
pm.max_children設定過高- 每個 worker 記憶體使用偏高
- 沒有 swap 緩衝
- 慢請求導致 worker 堆積
最終解法:
- 限制 max_children
- 建立 swap
- 開 slowlog 抓慢請求
- 設定 max_requests 避免 memory leak
🚀 建議最佳實務
| 設定 | 建議 |
|---|---|
| Swap | 一定要有(至少 4GB) |
| max_children | 用 RAM / worker RSS 計算 |
| max_requests | 300~1000 |
| slowlog | 必開 |
| request_terminate_timeout | 必設 |
📌 結論
OOM Killer 不是錯誤,它是保護機制。
真正的問題通常是:
- PHP-FPM 設定不合理
- 慢請求堆積
- 記憶體容量與負載不匹配
只要正確限制 worker 數量並建立 swap,伺服器穩定度會大幅提升。
如果你也遇到 php-fpm 被 OOM kill 的問題,希望這篇實戰紀錄能幫助你快速排查與解決。
近期留言