Apache 本身没有直接限制单个进程内存大小的配置指令,最稳妥的方式是结合系统级工具(如 cgroups 或 systemd)进行硬限制,同时配合 Apache 配置参数间接控制内存增长。
先说结论:单纯靠 Apache 配置无法硬性限制单个进程内存,建议采用“系统级限制 + 进程定期重启”的组合策略。
- 先定位:使用 ps 命令按内存排序,确认单个 apache2 进程的实际 RSS 内存占用。
- 先做:通过 systemd override 文件设置持久化内存上限,并调整 MaxRequestsPerChild 定期回收进程。
- 再验证:观察进程是否被限制在设定值内,且服务未因内存不足频繁崩溃。
命令速用版
如果你使用的是 systemd 管理的 Apache 服务,可以通过创建 override 文件持久化限制内存(例如限制为 512MB):
sudo systemctl edit apache2.service
在编辑器中输入以下内容并保存:
[Service] MemoryMax=512M
查看当前 Apache 进程内存占用的快速命令(按内存使用率排序):
ps aux `--sort`=-%mem | grep apache2 | grep -v grep | head -n 5
为什么会这样
Apache 的多处理模块(MPM)模式决定了内存使用方式。prefork 模式下每个请求对应一个进程,内存占用较高且容易累积;worker 或 event 模式采用多线程,相对节省内存。此外,代码中的内存泄漏或长时间运行的进程未及时释放资源,也会导致单个进程内存持续上涨。Apache 配置文件本身缺乏“单进程最大内存”这样的直接指令,因此需要借助操作系统层面的资源控制机制。
分步处理
1. 确认当前内存状况
使用 htop 或 top 命令,按内存排序,观察 apache2 进程的 RSS 值。如果个别进程异常偏大,可能存在泄漏。也可执行以下命令查看占用最高的前 5 个进程:
ps -eo pid,pmem,cmd `--sort`=-pmem | grep apache2 | head -n 5
2. 调整 Apache 配置间接控制
编辑 MPM 配置文件(如 /etc/apache2/mods-enabled/mpm_prefork.conf 或 mpm_event.conf):
- 设置 MaxRequestWorkers:限制并发进程总数,防止总内存耗尽。可根据公式估算:可用内存比例 × 总内存 / 单进程 RSS。
- 设置 MaxRequestsPerChild:建议设置为 10000 左右,让进程处理一定请求后退出重启,释放可能泄漏的内存。
- 调整 KeepAliveTimeout:设为较小值(如 5 秒),减少长连接占用。
注意:修改 Apache 配置后,必须重启服务才能生效。
sudo systemctl restart apache2
3. 使用系统级工具硬限制
若需严格限制单个进程,推荐使用 systemd override 方式,配置持久化且不易丢失。执行 systemctl edit apache2.service 后,添加 MemoryMax 参数。若使用 cgroups v2 手动管理,可创建组并写入 memory.max 文件,将进程 PID 加入该组,但 systemd 方式更便于维护。
怎么验证是否生效
对于 systemd 限制,可使用以下命令查看配置是否加载:
systemctl show apache2.service | grep MemoryMax
查看进程实际内存使用(单位 KB):
cat /proc/$(pidof apache2 | head -n 1)/status | grep VmRSS
同时持续监控 top 命令,确认进程内存未超过设定阈值,且服务日志中无频繁 OOM killed 记录。若发现进程频繁消失,可能是限制过低导致被系统杀死。
常见坑
- 限制过严导致服务不可用:若设置 MemoryMax 低于 Apache 正常启动需求,进程会被系统 OOM Kill,导致服务频繁重启。
- 忽略 MPM 模式差异:prefork 模式内存消耗远大于 event 模式,限制值需根据模式调整。
- 配置未重启生效:修改 Apache MPM 配置后忘记重启服务,导致配置不生效。
- 仅靠重启止血:定期重启 apache2 虽能释放内存,但未解决根本泄漏问题,应配合日志排查。