现代生产环境应选php-fpm而非mod_php,因其支持动态伸缩、平滑重启和细粒度资源控制;需匹配event mpm与keepalive、启用opcache并优化配置、禁用.htaccess解析以提升php执行效率。

Apache用mod_php还是php-fpm?先选对模式
直接决定PHP执行效率的底层机制,不是调几个参数就能补救的。mod_php把PHP解释器塞进每个Apache工作进程里,内存占用高、进程僵化;php-fpm是独立的PHP进程管理器,支持动态伸缩、平滑重启、更细粒度的资源控制——现代生产环境几乎都该选它。
确认当前模式:apachectl -M | grep php 如果看到 php7_module 或 php8_module,说明还在用 mod_php;如果没输出,但 systemctl is-active php-fpm 是 active,且 Apache 配置里有 ProxyPassMatch ^/(.*\.php)$ fcgi://127.0.0.1:9000/var/www/ 这类转发规则,那就是 php-fpm 模式。
- 新项目或已有站点能改就改:停掉 mod_php 模块(
a2dismod php8.2),启用proxy_fcgi和setenvif - PHP-FPM 的
pm = dynamic更稳妥,别盲目设成static;pm.max_children别只看CPU核数,要结合平均单请求内存(ps aux --sort=-%mem | grep 'php-fpm' | head -5看 RSS)来算 - Apache 侧必须加
ProxySet timeout=30 retry=0,否则网关超时会卡住整个连接队列
KeepAlive和MPM设置不匹配,PHP再快也白搭
Apache 的 MPM(多路处理模块)决定了它怎么调度连接,而 KeepAlive 行为直接影响 PHP 进程的复用率和等待时间。Prefork MPM 下开 KeepAlive 容易撑爆 MaxRequestWorkers;Event MPM 下不开 KeepAlive 又会让 PHP-FPM 白等一堆短连接。
查当前 MPM:apache2ctl -V | grep -i mpm。常见组合:
立即学习“PHP免费学习笔记(深入)”;
- Event + KeepAlive On:推荐。需确保
MaxRequestWorkers足够(比如 150),KeepAliveTimeout设低些(2–5秒),MaxKeepAliveRequests别设太高(100以内),避免长连接占着 PHP-FPM worker 不放 - Prefork 已淘汰,若无法升级,至少关掉 KeepAlive(
KeepAlive Off),并把MaxRequestWorkers控制在 50–100,否则 PHP 子进程会指数级膨胀 - 所有场景下,
Timeout建议设为 30,比 PHP 的max_execution_time大 5–10 秒,防止 Apache 先掐断连接
OPcache没开或配置太保守,等于没装PHP加速器
OPcache 是 PHP 自带的字节码缓存,不开它,每次请求都要重新解析、编译 .php 文件——这是最常被忽略的性能黑洞。注意:它只对 PHP-FPM 有效,mod_php 下虽可用但不稳定,不推荐。
检查是否启用:php -i | grep "opcache.enable",输出应为 on;再看 opcache.memory_consumption 是否 ≥ 128(单位 MB)。
-
opcache.memory_consumption = 256是较安全的起点,大站点可到 512;别设太高,超过物理内存 10% 可能引发系统 OOM -
opcache.max_accelerated_files = 7963(质数)或更高,尤其当 vendor 文件多时,否则会频繁踢出缓存 -
opcache.validate_timestamps = 0上线后必须关——开发期可设为 1,但生产环境留着就是定时拖慢 - 别漏掉
opcache.revalidate_freq = 0,它和上一条配合生效;还有opcache.fast_shutdown = 1,能略微缩短请求结束耗时
.htaccess和Directory配置导致重复解析开销
每请求一次 PHP 脚本,Apache 就会从根目录往上找一遍 .htaccess,再逐层合并 <directory></directory> 指令。如果站点根目录下有大量 AllowOverride All,又没关掉 FollowSymLinks,那每次请求都要做多次磁盘 stat 和正则匹配。
- 在主配置里用
<directory></directory>直接写死权限和重写规则,把AllowOverride None设为默认 - 真需要覆盖(如 WordPress 的 rewrite),只在必要目录开
AllowOverride FileInfo,而非All - 禁用
Options FollowSymLinks——除非你明确依赖符号链接;它会触发额外的lstat()系统调用 - 用
apache2ctl -t -D DUMP_RUN_CFG看最终生效的 Directory 配置层级,确认没有意外嵌套或重复定义
真正卡住 PHP 响应的,往往不是 mysql_query 多慢,而是 Apache 在进 PHP 之前就花了 80ms 查 .htaccess、等 KeepAlive 超时、或者用 Prefork 拉起第 200 个无谓的 PHP 进程。调参前先确认路径是否正确,比堆参数重要得多。











