4. CPU 控制器基础:cpu.weight、cpu.max 配置、CPU 时间分配与上限控制
CPU 控制器是 cgroup v2 中最核心的资源控制模块之一,它决定了进程组如何共享物理 CPU 时间。理解 cpu.weight 与 cpu.max 两个关键接口文件,是掌握 CPU 时间分配与上限控制的基础。本章将深入解析这两个参数的语义、配置方法以及它们在运行时生命周期中的观测要点。
4.1 CPU 控制器的核心接口
在 cgroup v2 的 CPU 子系统中,主要包含以下两个关键控制文件:
| 接口文件 | 控制语义 | 典型值范围 | 作用域 |
|---|---|---|---|
cpu.weight |
相对权重分配(比例共享) | [1, 10000],默认 100 | 同层 cgroup 之间竞争 CPU 时生效 |
cpu.max |
上限配额(带宽限制) | $quota $period,如 50000 100000 |
强制限制该 cgroup 的最大 CPU 使用量 |
关键区别:
cpu.weight 只在 CPU 资源紧张(争抢)时发挥作用;而 cpu.max 无论系统是否空闲,都会强制限制该 cgroup 的 CPU 使用上限。
4.2 cpu.weight:相对权重与比例分配
cpu.weight 实现了基于权重的比例共享(Proportional Share)调度。当多个 cgroup 同时需要 CPU 时,内核按照各 cgroup 的 weight 值比例分配 CPU 时间。
分配公式:
cgroup_i 获得的 CPU 时间比例 = cpu.weight_i / Σ(cpu.weight of all sibling cgroups)
配置示例:
# 创建两个子 cgroup
mkdir -p /sys/fs/cgroup/group-a
mkdir -p /sys/fs/cgroup/group-b
# 设置权重:group-a 获得 2 倍于 group-b 的 CPU 时间
echo 200 > /sys/fs/cgroup/group-a/cpu.weight
echo 100 > /sys/fs/cgroup/group-b/cpu.weight
# 将进程移入 cgroup
echo $PID_A > /sys/fs/cgroup/group-a/cgroup.procs
echo $PID_B > /sys/fs/cgroup/group-b/cgroup.procs
观测要点:在 CPU 争抢场景下,通过
cpu.stat 中的 usage_usec 字段可以验证实际分配比例是否与 weight 配置一致。若发现偏差,需检查是否存在 cpu.max 上限或 NUMA 亲和性干扰。
4.3 cpu.max:上限与带宽控制
cpu.max 采用令牌桶模型实现 CPU 带宽上限控制。格式为 $quota $period(单位微秒),含义是在每个 $period 周期内,该 cgroup 最多使用 $quota 微秒的 CPU 时间。
常见配置模式:
| 配置值 | 含义 | 等效 CPU 核数 |
|---|---|---|
100000 100000 |
每 100ms 周期最多使用 100ms CPU | 1 核 |
50000 100000 |
每 100ms 周期最多使用 50ms CPU | 0.5 核 |
200000 100000 |
每 100ms 周期最多使用 200ms CPU | 2 核 |
max 100000 |
无上限(默认值) | 不限 |
配置示例:
# 限制 group-a 最多使用 0.5 核 CPU
echo "50000 100000" > /sys/fs/cgroup/group-a/cpu.max
# 验证配置
cat /sys/fs/cgroup/group-a/cpu.max
# 输出: 50000 100000
常见陷阱:当
cpu.max 设置过小(如 10000 100000,即 0.1 核)时,进程可能频繁触发节流(throttle),导致 cpu.stat 中 nr_throttled 和 throttled_usec 持续增长。这是延迟异常的常见来源,需结合 cpu.pressure 指标综合判断。
4.4 CPU 时间分配与上限控制流程
下图展示了 cgroup v2 CPU 控制器的完整工作流程,从权重分配到上限检查,再到最终的调度决策:
4.5 运行时观测指标
通过 cpu.stat 文件可以获取 CPU 控制器的运行时状态,以下是关键观测字段:
| 字段名 | 含义 | 异常水位判断 |
|---|---|---|
usage_usec |
累计 CPU 使用时间(微秒) | 持续增长,结合 cpu.max 判断是否接近上限 |
user_usec |
用户态 CPU 时间 | 占比过高可能表示业务逻辑繁忙 |
system_usec |
内核态 CPU 时间 | 占比突增可能表示系统调用频繁或上下文切换过高 |
nr_periods |
cpu.max 周期总数 | 用于计算节流率的分母 |
nr_throttled |
被节流的周期数 | 若 > 0,表示该 cgroup 曾达到 CPU 上限 |
throttled_usec |
累计节流时间(微秒) | 持续增长表示 CPU 上限过紧,需调整 cpu.max |
延迟水位观测方法:计算节流率
throttle_ratio = nr_throttled / nr_periods。当节流率超过 5% 时,应视为延迟水位告警,表明该 cgroup 的 CPU 上限可能成为性能瓶颈。
4.6 权重与上限的协同配置策略
在实际生产环境中,cpu.weight 和 cpu.max 通常配合使用,形成“软限制 + 硬限制”的双层控制:
- 软限制(cpu.weight):定义各服务之间的优先级比例,确保高优服务在资源争抢时获得更多 CPU。
- 硬限制(cpu.max):防止单个服务突发占用过多 CPU 影响整机稳定性,常用于离线任务或非关键业务。
典型配置场景:
# 在线服务:高权重 + 宽松上限
echo 1000 > /sys/fs/cgroup/online/cpu.weight
echo "80000 100000" > /sys/fs/cgroup/online/cpu.max
# 离线任务:低权重 + 严格上限
echo 100 > /sys/fs/cgroup/offline/cpu.weight
echo "20000 100000" > /sys/fs/cgroup/offline/cpu.max
最佳实践:对于延迟敏感型服务,建议将
cpu.max 设置为略高于实际需求的配额(如 1.2 倍),同时保持高 cpu.weight,以兼顾稳定性和突发流量处理能力。