Select Page

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 原因:

  1. pm.max_children 設定過高
  2. 每個 worker 記憶體使用偏高
  3. 沒有 swap 緩衝
  4. 慢請求導致 worker 堆積

最終解法:

  • 限制 max_children
  • 建立 swap
  • 開 slowlog 抓慢請求
  • 設定 max_requests 避免 memory leak

🚀 建議最佳實務

設定建議
Swap一定要有(至少 4GB)
max_children用 RAM / worker RSS 計算
max_requests300~1000
slowlog必開
request_terminate_timeout必設

📌 結論

OOM Killer 不是錯誤,它是保護機制。

真正的問題通常是:

  • PHP-FPM 設定不合理
  • 慢請求堆積
  • 記憶體容量與負載不匹配

只要正確限制 worker 數量並建立 swap,伺服器穩定度會大幅提升。


如果你也遇到 php-fpm 被 OOM kill 的問題,希望這篇實戰紀錄能幫助你快速排查與解決。

相關資訊