phpEnv默认prefork MPM并发卡死在256,须改用event MPM、禁用mod_php切php-fpm、调ulimit及ServerLimit,并验证httpd -V输出为event且ps无多进程才生效。

phpEnv 默认用 prefork MPM,不改就卡死在 256 并发左右,根本撑不住真实流量。 它没开 event,也没调 ulimit,更没禁用 mod_php —— 这三样不处理,调 MaxRequestWorkers 就是白忙。
确认当前 MPM 是 prefork 还是 event
phpEnv 装完 Apache 后默认走 prefork,哪怕你手动改过配置,也可能因模块冲突回退。先验证:
执行 httpd -V | grep -i mpm,输出必须是 Server MPM: event 才算生效。如果看到 prefork,说明以下至少一条没做对:
- 没注释掉
LoadModule mpm_prefork_module - 没启用
LoadModule mpm_event_module modules/mod_mpm_event.so - phpEnv 的 PHP 是以
libphp模块方式加载的(即启用了mod_php),event 会自动降级
检查是否用了 mod_php:运行 httpd -M | grep php,若输出含 php7_module 或类似项,就不能用 event —— 必须切到 php-fpm + proxy_fcgi。
立即学习“PHP免费学习笔记(深入)”;
修改 phpEnv 的 Apache 并发参数位置
phpEnv 的 Apache 配置分散在多个地方,别去瞎改 httpd.conf 主文件。关键路径是:
C:\phpenv\apache\conf\extra\httpd-mpm.conf(Windows)或 /usr/local/phpenv/apache/conf/extra/httpd-mpm.conf(Linux)
这个文件默认被 httpd.conf 中的 Include conf/extra/httpd-mpm.conf 加载,但可能被注释了 —— 去掉前面的 #。
然后在该文件里找 <ifmodule mpm_event_module></ifmodule> 块(没有就自己加),写入:
StartServers 3 MinSpareThreads 75 MaxSpareThreads 250 ThreadsPerChild 32 MaxRequestWorkers 1024 MaxConnectionsPerChild 0
注意:MaxRequestWorkers 不能超过 ThreadsPerChild × ServerLimit,而 phpEnv 默认没设 ServerLimit,所以它隐式为 16(即 32×16=512)。要突破 512,得显式加一行 ServerLimit 32。
绕过系统级文件描述符限制(Windows 除外)
Linux 下即使 Apache 配好了,ulimit -n 默认常是 1024,MaxRequestWorkers 1024 就直接触发 Too many open files 错误。
检查实际生效值:cat /proc/$(pgrep httpd | head -1)/limits | grep "Max open files"
永久修复分两步:
- 用户级:编辑
/etc/security/limits.conf,加两行:www-data soft nofile 65536www-data hard nofile 65536(把www-data换成你的 Apache 运行用户,如apache或daemon) - 服务级:在 systemd 的
httpd.service文件里加LimitNOFILE=65536,然后systemctl daemon-reload && systemctl restart httpd
Windows 用户跳过这步,但要注意 mpm_winnt 模块不适用 —— phpEnv 在 Windows 下默认就是 mpm_winnt,它只允许一个进程,ThreadsPerChild 就是全局并发上限,建议设为 500~1000,别硬冲 2000+,否则线程调度反拖慢响应。
为什么改完还是卡?常见静默失效点
event 模式下最隐蔽的问题不是配置错,而是“看起来生效,其实没跑起来”:
-
httpd -V显示event,但ps aux | grep httpd看到一堆独立进程(prefork 特征),说明有非线程安全模块强制降级 —— 重点查mod_ssl、mod_evasive、自定义日志模块是否支持 TS(Thread-Safe) - PHP 没切到
php-fpm,httpd -M还能看到php7_module,此时 event 已失效,Apache 自动 fallback 到 prefork - KeepAliveTimeout 设成 30s,大量空闲连接占满线程,
MaxRequestWorkers再大也无用 —— 生产环境务必压到5或8 - 宝塔或 phpEnv 面板后台做了“一键优化”,覆盖了你手改的
httpd-mpm.conf—— 改完立刻httpd -t验证,再httpd -k graceful重载
真正卡住的地方,往往不在 Apache 配置本身,而在它和 PHP 的耦合方式 —— 不拆掉 mod_php,event 就永远是纸面参数。



















