PHP-FPM (FastCGI Process Manager) 是 PHP 運行在生產環境中最主流的進程管理方式。正確理解其啟動參數與配置文件,不僅能保證服務穩定運行,更是性能調優的基石。本文系統整理了啟動命令、核心配置項及常見坑點解決方案,供開發運維參考。
文中以常見編譯安裝路徑為例,實際操作請替換為您的實際路徑:
/usr/local/php/sbin/php-fpm/usr/local/php/etc/php-fpm.conf/usr/local/php/etc/php.ini修改配置後務必先測試,避免語法錯誤導致服務無法啟動:
# 基礎測試
/usr/local/php/sbin/php-fpm -t
# 指定配置文件測試
/usr/local/php/sbin/php-fpm -c /usr/local/php/etc/php.ini -y /usr/local/php/etc/php-fpm.conf -t
# 默認配置啟動
/usr/local/php/sbin/php-fpm
# 指定配置啟動
/usr/local/php/sbin/php-fpm -c /usr/local/php/etc/php.ini -y /usr/local/php/etc/php-fpm.conf
PHP-FPM 掌握信號控制,實現零停機重載:
# 關閉 (SIGINT)
kill -INT `cat /usr/local/php/var/run/php-fpm.pid`
# 平滑重啟 (SIGUSR2) - 推薦生產環境使用
kill -USR2 `cat /usr/local/php/var/run/php-fpm.pid`
提示: 平滑重啟會先啟動新進程處理新請求,舊進程處理完當前請求後退出,實現無縫切換。
配置文件採用 INI 格式,分為全局設置與池定義。以下針對高頻調優參數詳細說明:
| 參數 | 推薦值/說明 | 作用 |
|---|---|---|
| pid | run/php-fpm.pid | 主進程 PID 文件路徑,建議開啟便於管理腳本調用 |
| error_log | log/php-fpm.log | 錯誤日誌路徑,排查 502/503 錯誤的首要依據 |
| log_level | notice | 可選:alert/error/warning/notice/debug。生產環境建議 notice,調試時改 debug |
| daemonize | yes | 後台守護進程模式。調試時可改 no 直接在前台看輸出 |
static (靜態):固定子進程數 pm.max_children。適合內存充足、追求極致響應穩定的專用服務器。
dynamic (動態,默認):根據負載動態調整,由四參數控制:
pm.max_children:最大子進程數(硬上限,防止內存耗盡)pm.start_servers:啟動時創建的進程數pm.min_spare_servers:最小空閒進程數,低於此值創建新進程pm.max_spare_servers:最大空閒進程數,超過此值回收進程經驗公式:max_children = 總內存 * 0.8 / 單進程內存。單進程內存可通過 ps --no-headers -o "rss,cmd" -C php-fpm | awk '{sum+=$1} END {print sum/NR/1024 " MB"}' 估算。
listen = 127.0.0.1:9000 # TCP 模式,Nginx 配合 fastcgi_pass 使用
; listen = /tmp/php-fpm.sock # Unix Socket 模式,本機通訊性能更高(少一次 TCP 協議棧開銷)
listen.backlog = -1 # 內核監聽隊列長度,-1 交給系統決定(通常為 somaxconn)
listen.allowed_clients = 127.0.0.1 # 允許連接的客戶端 IP,多台 Nginx 時需放開或具體列出
; Unix Socket 權限設置 (僅 Socket 模式生效)
listen.owner = www
listen.group = www
listen.mode = 0666
| 參數 | 建議值 | 說明 |
|---|---|---|
| user / group | www / www | 運行進程的用戶組,需與 Nginx 用戶一致,確保文件讀寫權限 |
| pm.max_requests | 1000~20000 | 子進程處理多少請求後重生。防止第三方庫內存洩漏。0 表示不限。高併發建議調大(如 204800)減少重啟開銷 |
| request_terminate_timeout | 30s~60s | 單請求超時強制終止。解決 max_execution_time 在 FPM 下失效問題。頻繁 502 可適當調大 |
| request_slowlog_timeout | 5s~10s | 慢請求閾值,超時記錄調用棧到 slowlog,定位性能瓶頸神器 |
| slowlog | log/$pool.log.slow | 慢日誌路徑,配合 tail -f 實時監控 |
| rlimit_files | 65535 | 進程打開文件描述符上限,需配合 ulimit -n 系統限制 |
| catch_workers_output | yes | 捕獲子進程 stdout/stderr 到錯誤日誌,方便調試 var_dump 等輸出 |
pm.status_path = /status # 訪問 https://host/status 獲取進程池狀態(JSON/HTML/JSONP)
ping.path = /ping # 健康檢查端點,返回 pong,用於 LB/監控系統存活探測
ping.response = pong
chroot / chdir:目錄隔離與啟動目錄,增強安全性security.limit_extensions = .php .php7:限制可執行腳本後綴,防止惡意上傳執行現象:file_get_contents 訪問慢速外部 API 導致所有 php-fpm 進程阻塞,Nginx 返回 502。
根因:PHP max_execution_time 僅計算 CPU 時間,不含網絡等待;FPM 真正生效的是 request_terminate_timeout。
治標:設置合理超時(如 10s-30s)。
治本:給 HTTP 客戶端加超時控制:
$ctx = stream_context_create([
'http' => ['timeout' => 10] // 秒級超時
]);
file_get_contents($url, 0, $ctx);
或使用 cURL 設置 CURLOPT_TIMEOUT / CURLOPT_CONNECTTIMEOUT。
現象:高併發下進程頻繁重生,新請求擊中正在重啟的進程。
權衡:增大值減少重啟 vs 內存洩漏風險。建議:
① 優先排查代碼/擴展內存洩漏;
② 根據實際內存增長曲線設置(如 5000-20000);
③ 監控 pm.status_path 中 max children reached 指標。
# 配置
request_slowlog_timeout = 5s
slowlog = log/www.slow.log
# 實時查看
tail -f /usr/local/php/var/log/www.slow.log
日誌會完整記錄 PHP 調用棧,直觀暴露:
• 數據庫慢查詢 (mysqli_query, PDO::execute)
• 外部 API 阻塞 (curl_exec, file_get_contents)
• 遞歸/循環邏輯耗時
daemonize = yes,log_level = noticepm.max_children,啟用 dynamic 模式request_terminate_timeout = 30s 防止僵屍進程slowlog 閾值 5s,定期分析pm.status_path + ping.path 接入監控體系kill -USR2 平滑重啟釋放殘留資源核心思想:配置即代碼。將 php-fpm.conf 納入版本控制,配合監控指標持續迭代調優,而非一次配置終身不管。