这类问题我又碰上了一次。2 核 4G 的轻量服务器上跑 WordPress,php-fpm 的 pm 用 static 并设了 pm.max_children 50,白天访问一多系统就卡死,dmesg 里 OOM killer 把 php-fpm 子进程成片杀掉。

第一反应是「dynamic 模式没设 pm.max_spare_servers,空闲进程回收不掉」,验证下来不成立。

排查方向其实有限,先把可能性排一排。static 模式一次性起满进程,每个进程 60M 常驻,50 个就吃掉 3G;pm.max_children 是按并发数拍的,没按可用内存反算;PHP 扩展加载得多,单进程内存比预估高三倍。

量一个 php-fpm 进程的真实内存

ps -o rss,cmd -C php-fpm | awk '{s+=$1} END {print s/NR" KB"}'

结合可用内存反算子进程数

free -m && grep -n pm.max_children /etc/php-fpm.d/www.conf

随后改成 dynamic 并设好上下限

sed -i 's/^pm = .*/pm = dynamic/' /etc/php-fpm.d/www.conf

末了重启后观察进程数和内存曲线

systemctl restart php-fpm && watch -n2 'ps -C php-fpm --no-headers | wc -l'

当时还开着另一个排查窗口,两边日志对照着看才定位到。

改完先别撤,确认这几项。并发上来后 php-fpm 进程数在设定区间内波动,free -m 的 available 保持在 500M 以上,OOM 日志不再新增。

子进程数的经验算法是可用内存除以单进程 RSS 再打七折,留出的部分要够 MySQL 和系统用;别照抄别人的 50 或 100。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。

作者 9823189