报错是这么冒出来的。CentOS 7.9 上跑 Apache 2.4 的 prefork 模式,白天访问量上来后首页开始返回 503,error_log 里一行接一行 Server reached MaxRequestWorkers setting,把 MaxRequestWorkers 从 256 调到 400 后内存直接被吃光。
中间走过弯路,把「KeepAlive 开着但超时设成 15 秒,空闲连接白占 worker」当成主因,改完现象没变。
排查方向其实有限,先把可能性排一排。prefork 每个进程独占一份 PHP 模块内存,进程数上去内存就顶不住。还有一种是有慢接口长期占着 worker,队列排满后新请求直接被拒。
还有一种情况,MaxRequestWorkers 和 ServerLimit 不匹配,后者的上限把前者压住了。
上来先看当前有多少 worker 在忙
apachectl -M | grep prefork; ps aux | grep httpd | wc -l
再往下把长连接超时压短先释放空闲槽位
grep -nE 'KeepAlive|KeepAliveTimeout|MaxRequestWorkers|ServerLimit' /etc/httpd/conf/httpd.conf
接着按内存倒推一个安全的进程数
free -m && httpd -V | grep -i mpm
平滑重载并观察是否还报满
apachectl graceful && tail -f /var/log/httpd/error_log
怎么算真的好了,看的是同一批现象。error_log 里不再出现 MaxRequestWorkers 的告警,503 归零,free -m 里可用内存保持在 500M 以上。
补一句。并发靠加进程解决不了根本问题,PHP 站点换 php-fpm 加 event 模式更划算;改 ServerLimit 必须重启而不是 graceful。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。
