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 分配份额,边界清楚得多。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。
