Nginx 不直接解析 PHP,需通過 FastCGI 協議將動態請求轉發給 PHP-FPM (FastCGI Process Manager)。本文系統講解 FastCGI 工作原理、PHP-FPM 編譯安裝優化、Nginx 配置最佳實踐、緩存策略、超時參數調優、502 錯誤根因分析與排查體系。
location ~ \.php$)。/run/php/php8.2-fpm.sock) 或 TCP (127.0.0.1:9000) 封裝 FastCGI 協議數據包發送給 PHP-FPM Master 進程。關鍵優勢:進程持久化 (避免 CGI 每請求 fork)、職責分離 (Nginx 專注靜態/代理、PHP-FPM 專注業務)、可跨機器部署 (解耦擴展)。
./configure \
--prefix=/usr/local/php \
--with-config-file-path=/usr/local/php/etc \
--with-config-file-scan-dir=/usr/local/php/etc/php.d \
--enable-fpm \
--with-fpm-user=www --with-fpm-group=www \
--with-fpm-systemd \
--enable-opcache \
--enable-bcmath --enable-calendar --enable-exif \
--enable-ftp --enable-gd --enable-intl --enable-mbstring \
--enable-mysqlnd --enable-pcntl --enable-shmop --enable-soap \
--enable-sockets --enable-sysvmsg --enable-sysvsem --enable-sysvshm \
--enable-xml --enable-zip \
--with-curl --with-openssl --with-zlib --with-zip \
--with-jpeg --with-png --with-freetype --with-webp \
--with-mhash --with-sodium --with-password-argon2 \
--with-pear \
--disable-short-tags \
--disable-phpdbg \
--disable-cgi
make -j$(nproc) && make install
關鍵點:--enable-fpm 內建 FPM;--with-fpm-systemd 支持 systemd 通知;--enable-opcache 開啟 opcode 緩存 (生產必開);--disable-cgi 禁用舊版 CGI 接口。
[www]
user = www
group = www
listen = /run/php/php8.2-fpm.sock # Unix Socket 性能優於 TCP
listen.owner = www
listen.group = www
listen.mode = 0660
pm = dynamic
pm.max_children = 100 # 最大進程數 = 總內存 / 單進程內存 (留 20% 系統)
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 30
pm.max_requests = 1000 # 防止內存洩漏, 進程處理 1000 請求後重生
pm.status_path = /php_status
ping.path = /php_ping
request_terminate_timeout = 60s # 請求硬超時, 防卡死
request_slowlog_timeout = 10s
slowlog = /var/log/php-fpm/www-slow.log
rlimit_files = 65535
rlimit_core = 0
php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
php_admin_value[memory_limit] = 256M
php_admin_value[max_execution_time] = 60
php_admin_value[opcache.enable] = 1
php_admin_value[opcache.memory_consumption] = 256
php_admin_value[opcache.max_accelerated_files] = 20000
php_admin_value[opcache.revalidate_freq] = 60
# 上游定義 (支援多實例負載均衡)
upstream php_backend {
server unix:/run/php/php8.2-fpm.sock weight=1 max_fails=3 fail_timeout=30s;
# server 127.0.0.1:9000 weight=1; # TCP 方式
keepalive 64; # 長連接池, 減少握手
}
server {
listen 80;
server_name example.com;
root /data/www/example.com;
index index.php index.html;
# 靜態資源直接服務
location ^~ /static/ { expires 30d; access_log off; try_files $uri =404; }
location ^~ /uploads/ { expires 7d; location ~ \.php$ { deny all; } }
# PHP 動態請求
location ~ \.php$ {
try_files $uri =404; # 防止傳遞不存在文件到 PHP (安全)
fastcgi_pass php_backend;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# 緩存配置 (可選, 適用於高頻只讀接口)
fastcgi_cache PHP_CACHE;
fastcgi_cache_valid 200 301 302 30m;
fastcgi_cache_valid 404 1m;
fastcgi_cache_key $scheme$request_method$host$request_uri;
fastcgi_cache_bypass $http_cache_control; # 客戶端可繞過緩存
fastcgi_no_cache $http_cache_control;
# 超時參數 (關鍵防 502/504)
fastcgi_connect_timeout 5s;
fastcgi_send_timeout 60s;
fastcgi_read_timeout 60s;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 512k;
fastcgi_temp_file_write_size 512k;
}
# 前端控制器模式 (Laravel/ThinkPHP/Symfony)
location / {
try_files $uri $uri/ /index.php?$query_string;
}
}
| 指令 | 作用 | 推薦值 |
|---|---|---|
| fastcgi_cache_path | 定義緩存路徑、目錄層級、共享內存區、非活動過期 | /data/nginx/cache levels=1:2 keys_zone=PHP_CACHE:100m inactive=60m |
| fastcgi_cache_key | 緩存 Key 組成 | $scheme$request_method$host$request_uri |
| fastcgi_cache_valid | 按狀態碼設置過期時間 | 200 301 302 30m; 404 1m |
| fastcgi_cache_bypass / no_cache | 條件繞過/不緩存 | $http_cache_control $cookie_nocache $arg_nocache |
| fastcgi_buffer_size | 響應頭緩衝區大小 | 128k (含大 Cookie/Token 時需調大) |
| fastcgi_buffers | 響應體緩衝區數量和大小 | 4 256k (總 1MB, 覆蓋大多數頁面) |
| fastcgi_read_timeout | 讀取 FastCGI 響應超時 (防 504) | 60s (根據業務最長執行時間設置) |
| 錯誤 | 常見原因 | 排查命令/日誌 | 解決方向 |
|---|---|---|---|
| 502 | PHP-FPM 未啟動 / Socket 路徑錯誤 / 權限不足 | systemctl status php-fpm ls -l /run/php/ nginx error.log | 啟動服務、修正 socket 路徑、chown www:www socket 文件 |
| 502 | PHP-FPM 進程全部忙碌 / 進程數不足 | pm.max_children 達到上限、php_status 顯示 idle 0 | 調大 max_children、優化慢查詢、啟用緩存 |
| 502 | PHP 代碼致命錯誤 / 段錯誤 (Segfault) | php-fpm error.log dmesg | grep php | 修復代碼、更新擴展、檢查 opcache 衝突 |
| 504 | PHP 執行超過 fastcgi_read_timeout | nginx error.log: upstream timed out php-fpm slow.log | 調大 timeout、優化 SQL/邏輯、異步隊列處理耗時任務 |
| 504 | 資源耗盡 (內存/文件描述符) | free -h ulimit -n cat /proc/PID/limits | 調大 rlimit_files、優化內存洩漏、增加 swap |
pm.status_path,Prometheus 抓取 php-fpm-exporter 監控:active/idle 進程、請求耗時、慢請求數、內存使用。ngx_http_stub_status_module + nginx-prometheus-exporter 監控連接數、請求率、緩存命中率。掌握 Nginx + PHP-FPM 全鏈路原理與調優參數,是構建高併發、高可用 PHP 應用架構的核心內功。
Windows Server 2003 IIS 500 錯誤:Access 資料庫無法存取的完整解決方案
Linux 環境下 LAMP (Linux + Apache + MySQL + PHP) 完整編譯安裝指南
解決 IIS 啟用 Gzip 壓縮導致 OpenFlashChart 在 IE6 顯示「IO Error #2032」問題
phpMyAdmin 導入大文件突破 2MB 限制:無需修改 php.ini 的實戰方案
免費自架 SMTP 郵件伺服器:「寬帶 SMTP 服務器」快速部署指南
ASP.NET 1.1 / 2.0+ 跨站攻擊防護:machine.config / web.config 身分模擬與信任層級配置