导读:本期聚焦于美园和花创作的《Apache 虚拟主机如何利用 cgroup 实现资源隔离?完整配置指南》,敬请观看详情。一台服务器上跑多个网站,其中一个站点被突发流量打满CPU,导致其他虚拟主机全部卡死,这种问题该怎么解决?cgroup 是 Linux 内核提供的控制组机制,可以对进程组的 CPU、内存、磁盘 IO 等资源做精细化限制,把它和 Apache 的虚拟主机结合起来,就能让每个站点拿到明确的资源配额,互相之间互不干扰。本文先讲清 cgroup 的工作原理与版本差异,再演示如何定位 Apache 工作进程并绑定到对应的控制组,最后给出从单机测试到生产环境的完整配置流程,包括 CPU 份额、内存上限和 IO 带宽的限制方法,以及验证隔离效果的压力测试手段,帮你把多租户站点的稳定性真正控制在自己手里。

在一台 Apache 服务器上托管多个虚拟主机是常见的部署方式,但默认情况下所有虚拟主机共享同一组 Apache 工作进程,操作系统并不会区分哪个请求来自哪个站点。一旦某个站点出现异常流量或者跑了一段低效脚本,CPU、内存被瞬间吃光,其余站点跟着一起遭殃。要解决这个问题,光靠 Apache 自身的配置是不够的,需要在操作系统层面引入资源隔离机制,也就是 cgroup。

Apache 虚拟主机如何利用 cgroup 实现资源隔离?完整配置指南

cgroup 是什么,为什么它能隔离虚拟主机资源

cgroup 全称 control groups,是 Linux 内核从 2.6.24 版本开始引入的资源控制机制。它的核心思想是把一组进程放进一个"控制组",然后针对这个组设置资源上限,内核调度器和内存管理器会依据这些上限来分配资源。对 Apache 来说,只要能让不同虚拟主机的请求由不同进程池处理,再把每个进程池放进不同的 cgroup,就实现了站点级别的资源隔离。

cgroup 有两个主要版本。cgroup v1 中各个子系统(cpu、memory、blkio 等)各自挂载,管理灵活但配置分散;cgroup v2 使用统一的层级结构,所有资源控制器都挂在同一个树上,配置更简洁。CentOS 8、Ubuntu 21.10 之后的发行版默认都切换到了 v2。可以通过下面的命令确认当前系统使用的版本:

# 查看 cgroup 挂载信息,出现 cgroup2 字样说明是 v2
mount | grep cgroup
# 或者查看内核启动参数
cat /proc/filesystems | grep cgroup

需要提醒的是,v1 和 v2 的接口文件名完全不同。比如限制 CPU 在 v1 中是 cpu.shares,而在 v2 中是 cpu.weight。网上很多教程混用两种写法,照抄之前一定要先确认自己系统的版本,否则写入接口文件时会直接报错。

让每个虚拟主机使用独立的进程池

cgroup 管理的是进程,而 Apache 默认的 prefork 或 worker 模式下,所有虚拟主机共用同一批工作进程,这种情况下根本没有办法按站点隔离。解决办法是在 httpd.conf 中为每个虚拟主机配置独立的 MPM 进程池,让特定站点的请求只由专属进程处理。

以 event MPM 为例,先定义两个进程池,再分别指定给不同的虚拟主机:

<IfModule mpm_event_module>
    # 站点 A 的进程池,进程名前缀 sitea_
    <Proxy "unix:/run/sitea.sock|http://sitea-pool/">
        ProxySet min=2 max=10
    </Proxy>
</IfModule>

<VirtualHost *:80>
    ServerName www.a-ipipp.com
    # 通过 ProxyPass 把请求交给独立进程池
    ProxyPass "/" "http://sitea-pool/"
</VirtualHost>

除了这种代理方式,更直接的做法是使用 mod_cgid 配合不同的 Listen 端口,或者干脆为每个站点部署独立的 httpd 实例,每个实例监听不同端口、使用独立配置文件和运行用户。多实例方案虽然管理成本略高,但进程归属最清晰,后续绑定 cgroup 时不需要任何额外判断,特别适合站点数量不多的场景。

创建 cgroup 并绑定 Apache 进程

准备好独立进程之后,接下来创建控制组。生产环境推荐使用 systemd 来管理,避免手工创建的 cgroup 在重启后丢失。编辑或新建一个 slice 配置文件:

# /etc/systemd/system/sitea.slice
# 重新加载并启动
systemctl daemon-reload
systemctl start sitea.slice

对应的 slice 单元内容如下,限制该组最多使用 2 个 CPU 核心、4GB 内存:

[Unit]
Description=Resource limit for site A

[Slice]
CPUQuota=200%
MemoryMax=4G
CPUWeight=100

然后把 Apache 站点 A 的进程移入这个组。最可靠的方式是让对应的 httpd 实例由 systemd 直接管理,在其 service 文件中加入 Slice=sitea.slice,这样进程启动时自动归组,不存在遗漏。如果进程已经存在,也可以手工迁移:

# 找到站点 A 的进程号
pgrep -f "sitea"
# 写入 cgroup.procs 完成迁移(v2 示例)
echo 12345 > /sys/fs/cgroup/sitea.slice/cgroup.procs
# 验证进程归属
cat /proc/12345/cgroup

迁移完成后,无论站点 A 的脚本怎么失控,它的 CPU 使用率会被压制在 2 核以内,内存超过 4G 时内核会触发 OOM 杀掉越界进程,其他站点完全不受影响。这就是资源隔离的实际效果。

限制磁盘 IO 带宽并验证隔离效果

CPU 和内存之外,磁盘 IO 也常常是争抢的重点,尤其是有站点频繁写日志或做备份时。cgroup v2 中通过 io.max 接口限制带宽,systemd 单元里对应 IODeviceBandwidth 选项:

[Slice]
# 限制对 nvme0n1 设备的写入带宽为 50MB/s
IODeviceBandwidth=/dev/nvme0n1 50M

配置完成后务必做压力验证,不能想当然认为配置生效了。可以在站点 A 上跑一个死循环脚本模拟 CPU 打满,同时观察站点 B 的响应时间:

# 在站点 A 触发负载
ab -n 100000 -c 200 http://www.a-ipipp.com/heavy.php
# 同时观察各 cgroup 的实时资源消耗
systemd-cgtop
# 查看站点 A 是否被限制在配额内
cat /sys/fs/cgroup/sitea.slice/cpu.stat

如果看到 sitea.slice 的 CPU 使用稳定在 200% 封顶,而站点 B 的延迟曲线基本平稳,说明隔离已经生效。还要注意定期检查内存事件统计 memory.events,如果 oom_kill 计数持续增长,说明该站点的配额定得太紧,需要结合实际负载重新评估。资源隔离不是一次性配置,配额本身应该随着站点流量变化持续调整,才能真正在稳定性和资源利用率之间找到平衡点。

Apache虚拟主机cgroup资源隔离Linux资源限制修改时间:2026-09-10 21:59:03

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260910/54293.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。