先把当时的情况摆出来。Ubuntu 20.04 上 PHP 8.1,为了追吞吐把 pm 从 dynamic 改成 static,pm.max_children 设成 200,重启后内存使用率直接冲到百分之九十八,ssh 都登不进去,dmesg 里开始出现 out of memory。

把日志和配置对完,能解释这个现象的基本就这几处。static 模式启动就把全部子进程拉起来,每个进程的常驻内存立刻被占住。还有一种是单进程加载完框架和扩展大约三四十 M,两百个就是 7G 上下。

少数情况下是opcache 的共享内存另算,预加载文件多的话还要再加几百 M。不容易想到的是,系统里还有 MySQL 和 nginx,抢不到内存时内核开始杀进程。

第一件事是看清当前 pm 模式与进程数

grep -E '^pm|^pm.max_children|^pm.start_servers' /etc/php-fpm.d/www.conf

算一下 FPM 进程实际吃了多少

ps --no-headers -o rss -C php-fpm | awk '{s+=$1} END {print s/1024 " MB"}'

然后改回 dynamic 并按内存收紧上限

sed -i 's/^pm = .*/pm = dynamic/; s/^pm.max_children.*/pm.max_children = 40/' /etc/php-fpm.d/www.conf && systemctl restart php-fpm

末了确认内核没有再杀进程

dmesg -T | grep -i 'out of memory' | tail -3

怎么算真的好了,看的是同一批现象。free 的 available 回到 2G 以上,FPM 进程数随流量在十到四十之间浮动,dmesg 里不再出现 out of memory,ssh 登录恢复流畅。

static 只在请求量稳定且内存充裕时才有意义,动态站点用 dynamic 加合理的 max_children 更稳。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。

作者 9823189