PHP-FPM (FastCGI Process Manager) 是 PHP 官方內建的 FastCGI 進程管理器,自 PHP 5.3.3 起整合入核心。它採用 Master-Worker 架構:Master 進程負責管理 Worker 池、接收信號、平滑重載配置;Worker 進程實際處理請求。相較於舊式 spawn-fcgi,FPM 提供更精細的進程控制、記憶體限制、慢日誌、狀態頁面等企業級功能。
| 信號 | 動作 | 使用場景 |
|---|---|---|
INT / TERM | 立即終止所有進程(強制關閉) | 緊急停機、容器關閉 |
QUIT | 平滑終止:完成當前請求後退出 | 計劃性維護、部署前停機 |
USR1 | 重新打開日誌檔案(logrotate 配合) | 日誌切割、釋放磁碟空間 |
USR2 | 平滑重載:重新讀取配置、重啟 Worker、平滑切換 | 修改 php.ini / php-fpm.conf 後生效、程式碼部署 |
kill -USR2 `cat /usr/local/php/var/run/php-fpm.pid`
Master 會依序:
1. 重新讀取配置檔
2. 啟動新 Worker 池
3. 舊 Worker 處理完當前請求後自動退出
4. 新 Worker 完全接管流量
kill -QUIT `cat /usr/local/php/var/run/php-fpm.pid`
kill -TERM `cat /usr/local/php/var/run/php-fpm.pid`
kill -USR1 `cat /usr/local/php/var/run/php-fpm.pid`
ps aux | grep -c php-fpm
# 或更精確
pgrep -c php-fpm
若透過套件管理器安裝(如 yum install php-fpm 或 apt install php8.2-fpm),建議直接使用 systemd:
# 重載配置(平滑)
sudo systemctl reload php-fpm
# 重啟服務(會短暫中斷,約 100-500ms)
sudo systemctl restart php-fpm
# 停止
sudo systemctl stop php-fpm
# 查看狀態
sudo systemctl status php-fpm
# 即時追蹤日誌
sudo journalctl -u php-fpm -f
; 進程管理模式
pm = dynamic ; static / dynamic / ondemand
; static: 固定數量 Worker
; dynamic: 根據負載動態調整(需設定 pm.max_children, pm.start_servers, pm.min_spare_servers, pm.max_spare_servers)
; ondemand: 有請求才啟動 Worker,閒置超時關閉(適合低流量)
pm.max_children = 50 ; 最大 Worker 數(依記憶體估算:總記憶體 / 單進程記憶體)
pm.start_servers = 10 ; 啟動時 Worker 數
pm.min_spare_servers = 5 ; 最小閒置 Worker
pm.max_spare_servers = 20 ; 最大閒置 Worker
; 請求生命週期控制
pm.max_requests = 1000 ; 每個 Worker 處理 1000 請求後重生(防記憶體洩漏)
request_terminate_timeout = 60s ; 單請求最長執行時間
request_slowlog_timeout = 5s ; 慢日誌門檻
slowlog = /var/log/php-fpm/www-slow.log
; 記憶體保護
php_admin_value[memory_limit] = 256M
; 狀態頁面(需 nginx 配合 location /fpm-status)
pm.status_path = /fpm-status
ping.path = /fpm-ping
可用記憶體 = 總實體記憶體 - 系統保留 - MySQL/Redis 等其他服務記憶體
單進程記憶體 ≈ 30-50 MB (視框架、擴展而定,Laravel 约 40-60MB)
建議 max_children = 可用記憶體 / 單進程記憶體 * 0.8 (留 20% 緩衝)
# 範例:4GB 記憶體,系統保留 1GB,MySQL 1GB,剩 2GB
# 單進程 40MB => 2048 / 40 ≈ 51 * 0.8 ≈ 40
pm.max_children = 40
/etc/php-fpm.d/www.conf)php-fpm -t 測試語法reloading configuration 訊息request_terminate_timeout 設定過大或腳本 ignore_user_abort(true))kill -TERM `cat pid` 後再啟動pm.max_children 過小)/var/log/php-fpm/error.log)# Dockerfile 片段
FROM php:8.2-fpm-alpine
# 使用 dumb-init 作為 PID 1 處理信號轉發
RUN apk add --no-cache dumb-init
ENTRYPOINT ["dumb-init", "--"]
CMD ["php-fpm"]
# docker-compose.yml
services:
php:
build: .
# 平滑重載支援
stop_signal: SIGQUIT
# 健康檢查
healthcheck:
test: ["CMD-SHELL", "php-fpm -t"]
interval: 30s
timeout: 10s
retries: 3
掌握 PHP-FPM 信號控制與配置調優,是保障 PHP 應用高可用、零停機部署的核心技能。建議將平滑重載納入 CI/CD 流程,實現真正的持續部署。