在 Ubuntu 上提升 PHP-FPM 稳定性的实用方案
一 进程管理与资源配置
- 选择进程管理模式:波动流量用 pm=dynamic,稳定高并发用 pm=static,低频访问可用 pm=ondemand。
- 计算并限制并发进程数:先测量单个 PHP 进程常驻内存(如 10–30MB),再按“可用内存 × 0.7~0.8 ÷ 单进程内存”估算 pm.max_children,避免 OOM 与频繁回收。
- 动态模式常用基线:如 pm.start_servers=5、pm.min_spare_servers=3、pm.max_spare_servers=10;按需再上调。
- 进程回收与健康兜底:设置 pm.max_requests=1000 定期回收进程,缓解内存泄漏;在全局配置中启用 emergency_restart_threshold=10、emergency_restart_interval=1m,在异常退出激增时自动重启守护进程,作为安全网。
二 请求与进程生命周期控制
- 设置请求超时:用 request_terminate_timeout(如 30s)作为硬超时,终止卡死脚本,保护后端资源。
- 慢请求定位:开启 slowlog 与 request_slowlog_timeout(如 5s),持续收集长耗时调用栈,优先优化慢点。
- 缓冲与日志:开启 catch_workers_output=yes,将子进程输出接入日志,便于排错;同时配置 php_admin_value[error_log] 与 php_admin_flag[log_errors] 输出到指定错误日志。
三 通信方式与上游容错
- 传输方式取舍:本地优先 Unix Socket(如 unix:/run/php/php8.3-fpm.sock),性能更好;极端高并发或遇到 socket 不稳定/502 时,可改用 127.0.0.1:9000 或同时提供多路后端。
- 多进程池与 Nginx upstream:为不同应用或租户配置多个 pool + 不同 socket,在 Nginx 中做 upstream 轮询/故障隔离,显著降低单点 socket 拥塞导致的整体失败率。
- 访问控制:若使用 TCP,建议设置 listen.allowed_clients=127.0.0.1 仅本机访问;Socket 文件权限与属主需与 www-data 或指定运行用户一致。
四 监控 告警与日常维护
- 内置状态页:在 pool 配置启用 pm.status_path=/status,Nginx 暴露只读接口(如 location /fpm-status)并结合 allow/deny 限制来源;持续观察 active processes、排队与拒绝情况,作为调参依据。
- 系统监控与日志:用 systemd 与 journalctl -u php8.x-fpm -f 实时看错误与重启;配合 top/htop/vmstat/iostat/netstat/sar/iftop 定位资源瓶颈;用 logrotate 管理 PHP-FPM 与 Nginx 日志,避免磁盘被占满引发故障。
- 变更与升级:变更前备份配置与数据;保持 Ubuntu 与 PHP-FPM 的安全更新与补丁,减少稳定性与安全风险。
五 一键可用的安全基线示例
- 假设环境:PHP 8.3、可用内存 2GB、单进程约 30MB、本地 Unix Socket。
- 计算:max_children ≈ 2GB × 0.75 ÷ 30MB ≈ 50(留足系统与其他服务内存)。
- pool 关键项(/etc/php/8.3/fpm/pool.d/www.conf):
- 进程管理:
- pm = dynamic
- pm.max_children = 50
- pm.start_servers = 5
- pm.min_spare_servers = 3
- pm.max_spare_servers = 10
- pm.max_requests = 1000
- 生命周期与日志:
- request_terminate_timeout = 30s
- slowlog = /var/log/php-fpm/www-slow.log
- request_slowlog_timeout = 5s
- catch_workers_output = yes
- php_admin_value[error_log] = /var/log/php-fpm/www-error.log
- php_admin_flag[log_errors] = on
- 通信与权限:
- listen = /run/php/php8.3-fpm.sock
- listen.owner = www-data
- listen.group = www-data
- listen.mode = 0660
- Nginx 片段:
- fastcgi_pass unix:/run/php/php8.3-fpm.sock;
- include fastcgi_params;
- fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
- 重载与验证:
- sudo systemctl reload php8.3-fpm
- sudo systemctl reload nginx
- curl -I http://your-site/health.php 与访问 /fpm-status 检查状态与连通性。