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 控制器的完整工作流程,从权重分配到上限检查,再到最终的调度决策:

CPU 控制器工作流程:权重分配与上限检查 进程组(cgroup) cpu.weight 检查 相对权重比例计算 cpu.max 检查 配额/周期令牌桶判断 CFS 完全公平调度器 物理 CPU 执行 节流(Throttle)事件 说明:cpu.weight 决定争抢时的比例,cpu.max 决定上限;两者同时配置时,先检查上限,再按权重分配剩余资源

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,以兼顾稳定性和突发流量处理能力。