给服务设资源上限
systemd 统一用 cgroup 管理服务资源:在单元里写 MemoryMax、CPUQuota 等字段,就能把某个服务的资源占用关在上限之内。最大的价值不是省资源,而是缩小故障范围——某个服务内存失控时,OOM 只在该单元内部发生,不会把整机的关键进程一起带走。systemd-cgtop 提供按单元的实时占用视图,用来确认限制是否真的生效。
基本信息
| 内存上限 | MemoryMax=(硬上限)、MemoryHigh=(软上限) |
|---|---|
| CPU 上限 | CPUQuota=百分比,150% 表示最多 1.5 个核 |
| 进程数 | TasksMax= |
| I/O 权重 | IOWeight=(相对权重) |
| 查看占用 | systemd-cgtop -m、systemctl status 的资源段 |
| 生效方式 | daemon-reload 后重启对应服务 |
典型使用场景
- 同一台机器上跑多个业务,防止单个服务吃满内存拖垮整机
- 限制构建或批处理服务的 CPU,避免抢占在线请求的资源
- 容器化之前的过渡方案:先用 systemd 单元做资源隔离
- 排查内存异常时通过 cgtop 定位到具体是哪个单元在涨
- 按业务等级给不同服务分配不同的资源配额
配置与生效
配置与生效
mkdir -p /etc/systemd/system/myapp.service.d # drop-in 目录,避免直接改原单元文件
cat > /etc/systemd/system/myapp.service.d/20-limits.conf <<'EOF'
[Service]
MemoryMax=2G # 硬上限,触顶在该单元内触发 OOM
CPUQuota=150% # 最多使用 1.5 个核的算力
TasksMax=512 # 限制可创建的进程与线程总数
EOF
systemctl daemon-reload && systemctl restart myapp
systemctl show myapp -p MemoryMax -p CPUQuota -p TasksMax # 确认取值已生效观察与排障
观察与排障
systemd-cgtop -m # 按内存占用排序,实时看各单元使用了多少
systemctl status myapp | grep -iE 'memory|cpu' # 状态输出里能看到当前占用与峰值
cat /sys/fs/cgroup/system.slice/myapp.service/memory.max 2>/dev/null # cgroup v2 直接读限制值
journalctl -u myapp | grep -i -E 'oom|killed' | tail # 被 OOM 杀掉的记录
systemd-cgls # 查看 cgroup 层级,确认服务归属哪个 slice参数与效果
| 参数 | 作用 | 设错的表现 |
|---|---|---|
| MemoryMax | 内存硬上限 | 过小则服务被反复 OOM 重启 |
| MemoryHigh | 内存软上限,超限先回收 | 只设 High 不会阻止失控增长 |
| CPUQuota | CPU 配额 | 过小则请求排队、响应变慢 |
| TasksMax | 进程与线程总数 | 过小导致 fork 失败、连接建不上 |
| IOWeight | I/O 相对权重 | 只影响竞争时的分配比例,不是硬上限 |
| Slice | 归属的资源分组 | 归错 slice 会继承另一套限制 |
CPUQuota=150% 表示至多得到一个半核的算力,它与 nice 不同:nice 只在竞争时影响调度顺序,CPUQuota 是硬性配额,超出部分会被限流。
cgroup 版本不同行为略有差异:cgroup v2 是当前主流,读限制值可看 /sys/fs/cgroup 下对应单元的 memory.max 等文件,v1 路径与字段名不同,排查前先确认版本。