CentOS 7.9 上跑一个多进程计算服务,四十个 worker 抢不到 CPU,nice 全是 0,top 里每个进程只占 2% 左右,机器整体负载并不高,同一个 cgroup 里还有日志进程。

一开始怀疑是「日志进程单独一个会话,反而拿到了同等的调度份额」,查了一圈,方向不对。

把日志和配置对完,能解释这个现象的基本就这几处。内核的 sched_autogroup 按会话分组,一个 shell 起的进程共享同一份额度。另一种情况是worker 都在同一个终端会话里 fork,被归成一组互相分时间。

不容易想到的是,systemd 启动的服务按 slice 分组,和手工跑的进程不在一个维度上比。

上来先看 autogroup 是否开着

cat /proc/sys/kernel/sched_autogroup_enabled

接着确认进程归属的调度组

cat /proc/$(pgrep -f worker | head -1)/autogroup

随后关掉 autogroup 再压测对比

sysctl -w kernel.sched_autogroup_enabled=0

等前面都确认过,再用 cgroup 给日志进程限额度

systemctl set-property app-log.service CPUQuota=20%

恢复的判定其实很直接。worker 的 CPU 占用回到接近均分,整体吞吐提升三成,日志进程不再和计算进程同权抢占。

这里还有个坑。autogroup 对桌面交互友好,对服务器上的多进程服务反而添乱;关掉之后按 cgroup 分配份额,边界清楚得多。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。

作者 9823189