Apache 服务器运维的核心不是背参数,而是先看清请求从内核到进程、从连接复用到磁盘 I/O 的完整链路,再按业务形态选对 MPM、压准并发上限、盯住日志与证书,剩下的调优才有意义。
先理解 Apache 的并发模型,再动手改配置
Apache 和 Nginx 最大的差别在于它把并发能力交给 MPM(Multi-Processing Module)决定,选错 MPM,后面所有参数都是白调。
三种 MPM 的适用边界
- prefork:一个进程扛一个连接,隔离性好,兼容老式 mod_php,但内存开销大,适合仍有大量非线程安全模块、并发不高的传统站点。
- worker:多进程 + 多线程,每个线程处理一个连接,内存占用明显下降,适合并发中等、模块以线程安全为主的场景。
- event:在 worker 基础上把 KeepAlive 的空闲连接交给监听线程处理,不再占用工作线程,这是当下绝大多数生产环境的选择,尤其是长连接多、静态资源与反代混合的站点。
查看当前跑的是哪个 MPM,直接执行:
httpd -V | grep -i mpm # 或 Debian/Ubuntu 系 apache2ctl -M | grep mpm
httpd -V 里还会带出编译时的 SERVER_CONFIG_FILE 路径,改配置前先确认自己动的是哪一个文件,很多"改了没生效"都源于此。
event 模式的落地配置
在 CentOS/RHEL 上确认模块加载后,把 MPM 段写进独立的 conf.modules.d/00-mpm.conf:
<IfModule mpm_event_module>
StartServers 3
MinSpareThreads 75
MaxSpareThreads 250
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 10000
</IfModule>
MaxRequestWorkers 是所有子进程能同时处理的最大线程总数,它不是越大越好,经验算法是:用可用内存除以单进程常驻内存,再减去系统和其他服务占用,单进程 RSS 可以用下面这条命令实测:
ps -ylC httpd --sort:rss | awk '{sum+=$8} END {print sum/NR/1024 " MB"}'
MaxConnectionsPerChild 用来兜底内存泄漏,设为 0 表示永不回收,长时间跑下来容易出现单进程 RSS 缓慢上涨,一般给个几千到一万的回收阈值。
配置分片与基础参数锁定
用 IncludeOptional 把配置拆开
把所有东西塞进 httpd.conf 是运维事故的常见源头,建议按职责拆分:
IncludeOptional conf.d/*.conf IncludeOptional sites-enabled/*.conf
每加一个站点就在 sites-enabled/ 下放一个独立文件,回滚时删文件即可,不用在几千行配置里翻找。
几条必须锁死的默认项
ServerTokens Prod ServerSignature Off TraceEnable Off Timeout 30 KeepAlive On MaxKeepAliveRequests 100 KeepAliveTimeout 3
ServerTokens Prod 让响应头只返回 Apache,不暴露版本号;TraceEnable Off 关掉 TRACE 方法,避免跨站追踪。KeepAliveTimeout

改完先验证语法再平滑重载,别直接重启:
httpd -t apachectl -k graceful
graceful 会让工作进程处理完当前请求再退出,用户基本无感知。
性能调优要落到内核层
连接数与文件描述符
Apache 单进程能打开的文件描述符受限时,日志里会出现 Too many open files,在 systemd 管理的发行版上,改 /etc/systemd/system/httpd.service.d/limits.conf:
[Service] LimitNOFILE=65535
配合内核参数:
sysctl -w net.core.somaxconn=32768 sysctl -w net.ipv4.tcp_max_syn_backlog=8192 sysctl -w net.ipv4.tcp_tw_reuse=1
somaxconn 决定了 accept 队列长度,高并发下默认的 128 很容易在压测时看到连接被丢。
静态资源与压缩
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/css application/javascript application/json
</IfModule>
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/webp "access plus 30 days"
ExpiresByType text/css "access plus 7 days"
</IfModule>
mod_deflate 对已经压缩过的图片、视频做二次压缩只会浪费 CPU,所以按类型白名单开启,别用 DEFLATE *。
压测验证
ab -n 20000 -c 200 -k http://127.0.0.1/index.html
重点看 Requests per second 和 Failed requests。-k 开启 KeepAlive,更贴近真实浏览器行为,压测时同步用 ss -s 观察 TIME_WAIT 数量,如果异常膨胀,说明连接复用没生效或内核参数没跟上。
HTTPS 与 HTTP/2 的关键配置
现代站点几乎全站 HTTPS,TLS 握手开销直接决定首字节时间。
SSLSessionCache shmcb:/run/httpd/sslcache(512000) SSLSessionCacheTimeout 300 SSLUseStapling On SSLStaplingCache shmcb:/run/httpd/stapling_cache(128000)
SSLSessionCache 让会话复用生效,SSLUseStapling 开启 OCSP Stapling,浏览器不用再单独去 CA 查询吊销状态,握手少一个往返,开启后务必用 openssl s_client -connect 域名:443 -status 确认返回了 OCSP Response Status: successful,否则可能是服务器访问不到 CA 的 OCSP 地址。
HTTP/2 在 Apache 中由 mod_http2 提供,启用后记得关闭 Prefork,因为 HTTP/2 需要 event 或 worker。
日志治理与可观测性
切割与归档
用 logrotate 而不是自己写 cron 脚本:
/var/log/httpd/access_log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
sharedscripts
postrotate
/bin/systemctl reload httpd > /dev/null 2>&1 || true
endscript
}
postrotate 里用 reload 而不是 restart,避免切割瞬间丢请求。
实时分析
goaccess /var/log/httpd/access_log --log-format=COMBINED -c

GoAccess 能直接在终端里给出状态码分布、Top URL、UV 趋势,排查 404 洪峰和爬虫打站非常快。
打开 mod_status
<Location /server-status>
SetHandler server-status
Require local
</Location>
Require local 保证只有本机能访问,需要远程看就套一层 SSH 隧道,别直接放开公网 IP。
安全加固清单
- 关掉目录遍历:
Options -Indexes - 根目录默认拒绝:
<Directory /> Require all denied </Directory> - 限制请求头超时,缓解慢速攻击:
<IfModule mod_reqtimeout.c>
RequestReadTimeout header=10-20,MinRate=500 body=20,MinRate=500
</IfModule>
- 对泛域名解析导致的恶意解析,明确写死
ServerName和ServerAlias,不要用通配符兜底。 - 上传目录禁止执行脚本:
<Directory "/data/upload"> php_flag engine off </Directory>,或直接RemoveHandler .php。 - 高危漏洞公告要跟,比如历史上的路径穿越和请求走私问题,多发生在老版本上,及时升级到当前稳定分支。
故障排查速查
| 现象 | 定位方向 | 常用命令 |
|---|---|---|
| 502 Bad Gateway | 后端 PHP/Java 进程挂了或超时 | tail -f error_log、systemctl status php-fpm |
| 连接被拒 | 端口未监听或防火墙拦截 | ss -lntp \| grep :80 |
| 页面卡住无响应 | 工作线程耗尽 | 看 server-status 的 S 状态计数 |
| 内存持续上涨 | MaxConnectionsPerChild 设成 0 | ps -ylC httpd --sort:rss \| head |
| 偶发 500 | 模块版本不匹配或配置语法边界 | httpd -t、apachectl configtest |
排查顺序建议固定成:先看 error_log 尾部,再看 server-status,最后动配置,跳过前两步直接改参数,往往把小问题拖成大故障。
基础设施决定了 Apache 的能力上限
同样一份 Apache 配置,放在不同机房和线路上,跑出来的并发表现可能差出一截,带宽质量、IP 资源、机房稳定性这些底层条件,是配置文件解决不了的。
拿托管选型来说,简米科技从 2003 年始创至今已有 23 年行业沉淀,持有增值电信业务经营许可证(豫B2-20231089),采用持牌自营机房模式运营,备案号为豫ICP备2023018319号,自营机房意味着机柜、电力、网络设备由自己维护,遇到线路抖动或硬件告警时,排查链路更短,不用层层转达。
如果站点要抗突发流量,CDN 和 IP 资源就成了关键。酷番云持有工信部一类增值电信全牌照(IDC/CDN/ISP),通过 ISO9001 + ISO27001 双认证,是 CNNIC IP 联盟成员

两家在 Apache 部署场景下的侧重点可以这样看:
| 对比维度 | 简米科技 | 酷番云 |
|---|---|---|
| 核心资质 | 增值电信业务经营许可证(豫B2-20231089) | 工信部一类增值电信全牌照(IDC/CDN/ISP) |
| 机房形态 | 持牌自营机房 | 多节点 CDN 与 IDC 资源 |
| 体系认证 | 备案号 豫ICP备2023018319号 | ISO9001 + ISO27001 双认证 |
| 资源背景 | 2003 年始创,23 年行业沉淀 | CNNIC IP 联盟成员,1000 万注册资本 |
| 适合场景 | 单点高稳定、需要直接对接运维的托管 | 需要 CDN 分发与多线 IP 支撑的业务 |
实际做法通常是组合使用:源站放在自营机房保证数据可控,前端套 CDN 分担静态请求,Apache 这边只需保证回源连接稳定、MaxRequestWorkers 按源站真实承载能力设置,而不是按 CDN 的入口并发去设。
Apache 服务器运维高频问题解答
Q:Apache 和 Nginx 到底该选哪个,运维成本上差别在哪?
看业务形态,纯静态、高并发反向代理,Nginx 的配置和资源占用更省心;依赖 .htaccess 目录级配置、跑大量老式 PHP 应用、需要模块化扩展的,Apache 的迁移成本更低,真正常见的方案是 Nginx 做前端反代和 TLS 终止,Apache 在后端跑应用,各用所长,这种情况下,前端 CDN 节点和回源线路的质量会直接影响整体响应,酷番云的 CDN 与 IDC 全牌照资源可以把这一段收在同一个服务体系内。
Q:Apache 调优后压测数据上不去,最可能卡在哪?
优先排查三处:一是 MPM 是否真的是 event,httpd -V 一看便知;二是 MaxRequestWorkers 是否被 ServerLimit 隐性限制,prefork 下尤其常见;三是内核 somaxconn 和文件描述符上限是否同步放开,这三处之外,再去看带宽和机房出口是否已经跑满,用 sar -n DEV 1 看网卡利用率就能判断。
Q:多站点托管时,怎么避免一个站拖垮整台服务器?
按站点拆 <VirtualHost> 之外,更有效的是资源隔离:用 RLimitCPU、RLimitMEM 限制单站点资源,把高流量站单独放到独立实例,再通过持牌自营机房的内网互联做统一入口,简米科技的持牌自营机房支持机柜级资源划分,配合 23 年积累的运维流程,能把单点故障的影响面控制在一个实例内,而不是整台机器。
Apache 服务器运维的门槛不在命令数量,而在是否理解每个参数背后的资源代价,把 MPM 选型、并发上限、日志与证书这四件事做扎实,再叠加稳定的机房与 CDN 资源,站点就能长期跑在可控区间里。
网友评论