一台 8 核 16G 的机器上跑了两组 FPM pool,网站一组、离线任务一组,每天凌晨跑批开始后网站的 p99 从两百毫秒涨到三秒,CPU 使用率倒是一直只有六成。

把日志和配置对完,能解释这个现象的基本就这几处。跑批的 pool 把 pm.max_children 开得很大,几十个进程一起抢 CPU 时间片;两组进程共用同一块磁盘,跑批大量读文件,网站的模板读取被拖慢;没有做 CPU 亲和性划分,调度器在两组进程之间来回搬,缓存命中率下降;跑批请求里有大量阻塞调用,占着进程却几乎不消耗 CPU,看着空闲实则排队。

上来先看两组 pool 的进程数与上限

grep -E '^\[|^pm|^pm.max_children' /etc/php-fpm.d/*.conf

实时看哪些进程在吃 CPU

ps -eo pid,psr,pcpu,cmd -C php-fpm --sort=-pcpu | head

接着把跑批那组的进程数收紧

sed -i 's/^pm.max_children.*/pm.max_children = 8/' /etc/php-fpm.d/batch.conf && systemctl reload php-fpm

再给跑批单独套一层 CPU 配额

systemd-run --scope -p CPUQuota=200% php /www/batch/run.php

改完先别撤,确认这几项。跑批期间网站 p99 稳定在三百毫秒以内,load 不再随跑批时间线性上升,两组进程的 CPU 占比各自平稳。

补一句。物理隔离比调参可靠,有条件就把离线任务挪到独立机器;同一台机器上至少要把进程数和配额分开算。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。

作者 9823189