当前位置:首页 > 文章列表 > 文章 > linux > cgroup v2 限制服务内存并观察回收事件

cgroup v2 限制服务内存并观察回收事件

来源:17golang原创 2026-10-03 21:31:11 0浏览 收藏

服务内存异常时,先别急着把机器的总内存调大。cgroup v2 更适合把“这一个服务最多能用多少”和“达到压力后如何回收”拆成两层:用 memory.high 施加回收压力,用 memory.max 设置硬边界,再用 memory.current、memory.events 和 memory.events.local 判断究竟发生了什么。

要点速览
  • memory.high 是压力阈值,超过后会触发更重的回收和节流,不等同于立即 OOM。
  • memory.max 是硬上限,无法回收时可能在该 cgroup 内触发 OOM。
  • memory.events 默认包含层级统计,定位当前服务时还要对照 memory.events.local。

一、先确认主机真的使用 cgroup v2

先查看挂载点和可用控制器。以下命令只读系统状态,示例路径假定统一层级挂在 /sys/fs/cgroup。

# 确认目标目录是否为 cgroup2 文件系统
stat -fc %T /sys/fs/cgroup

# 查看当前层级可以向子 cgroup 提供哪些控制器
cat /sys/fs/cgroup/cgroup.controllers

# 查看根层级已经向子 cgroup 开启了哪些控制器
cat /sys/fs/cgroup/cgroup.subtree_control

第一条命令应看到 cgroup2fs。如果 cgroup.controllers 中没有 memory,先检查内核配置、挂载方式和上级层级,而不是直接向目标目录写入 memory.max。v2 的控制器需要由父层级通过 cgroup.subtree_control 提供给子层级。

cgroup v2 控制器准备与服务内存文件的静态结构说明图
图1:cgroup v2 的控制器准备、服务 cgroup 与内存接口文件之间的静态关系;这是原创结构说明图,不是终端截图。

二、为服务建立 memory.high 和 memory.max 边界

确认控制器可用后,创建一个只用于示例服务的叶子 cgroup。这里把可回收压力阈值设为 512 MiB,把硬上限设为 768 MiB;实际数值应根据服务稳定工作集、缓存策略和突发流量压测结果确定。

# 创建服务专用的 cgroup 目录
sudo mkdir -p /sys/fs/cgroup/demo-api

# 超过该值后增加回收压力和节流,但不直接等同于 OOM
echo 512M | sudo tee /sys/fs/cgroup/demo-api/memory.high

# 无法继续回收时的硬边界;max 表示不设硬上限
echo 768M | sudo tee /sys/fs/cgroup/demo-api/memory.max

# 读取内核实际接受的值,避免只相信写入命令没有报错
cat /sys/fs/cgroup/demo-api/memory.high
cat /sys/fs/cgroup/demo-api/memory.max

memory.high 适合做服务保护的第一道边界:它让超出阈值的工作负载承受更强回收压力。memory.max 才是硬限制,但内核文档也明确指出,某些情况下使用量可能暂时超过它,且部分分配路径不会按普通 OOM 方式处理。因此这两个值不能简单理解成“512 MiB 和 768 MiB 两个精确瞬时开关”。

三、让服务进程真正归属这个 cgroup

只创建目录并不会改变服务归属。对已经启动的单进程服务,可以把 PID 写入 cgroup.procs;systemd 管理的服务则更适合把限制写到 unit,让重启后仍然有效。

# 读取目标服务的 PID;这里的服务名仅作示例
pid="$(systemctl show -p MainPID --value demo-api.service)"

# 把主进程加入目标 cgroup,生产环境还要确认子进程继承和权限边界
echo "$pid" | sudo tee /sys/fs/cgroup/demo-api/cgroup.procs

# 核对 PID 当前是否已经出现在目标 cgroup
grep -w "$pid" /sys/fs/cgroup/demo-api/cgroup.procs

如果服务由 systemd 托管,持久配置可以使用资源控制属性:

# 为 unit 写入可持久化的内存压力阈值和硬上限
sudo systemctl set-property demo-api.service MemoryHigh=512M MemoryMax=768M

# 查看 systemd 展开的属性,确认 unit 层配置已生效
systemctl show demo-api.service -p MemoryHigh -p MemoryMax

手工写 cgroup 文件适合排查和一次性实验;长期运行的服务应让 systemd 或其他编排层成为唯一配置来源,避免重启、迁移和子进程管理把限制丢掉。

四、用 current 和 events 判断发生了哪类压力

先看当前使用量,再看事件计数。计数变化说明边界曾被触碰,但不能单独证明某一次请求就是唯一原因。

# 当前 cgroup 的内存使用量,单位为字节
cat /sys/fs/cgroup/demo-api/memory.current

# 读取包含子层级的事件统计
cat /sys/fs/cgroup/demo-api/memory.events

# 只读取 demo-api 自身产生的事件,便于排除子 cgroup 干扰
cat /sys/fs/cgroup/demo-api/memory.events.local

常见字段可以这样理解:

字段它说明什么排查重点
high内存使用触碰过 high 边界工作集是否长期高于阈值,是否出现持续节流
max使用量触碰过 max 边界回收是否跟不上,是否需要拆分缓存或降低并发
oomcgroup 内发生过 OOM 触发结合服务日志和进程退出时间判断影响面
oom_kill发生过 OOM kill优先保留计数与日志,不要只看一次 current
memory.current 与 memory.events 回收和 OOM 统计边界的静态结构说明图
图2:当前使用量、high/max 边界与 events 统计字段的静态关系;这是原创结构说明图,不是运行结果截图。

五、按照现象调整,而不是看到 max 就盲目放大

如果 high 持续增长而 oom_kill 不变,通常先检查工作集、缓存上限和并发,再评估是否提高 memory.high。如果 max、oom 或 oom_kill 增长,要把它当作硬边界告警,核对服务是否被杀、是否有子 cgroup 分摊,以及 memory.events 的层级统计是否把后代事件算进来了。

复查时至少保留三份信息:限制值(memory.high、memory.max)、当前值(memory.current)和事件快照(memory.events.local)。如果需要主动回收,memory.reclaim 可以触发目标 cgroup 的回收,但它是管理接口,不能用来伪造“发生了内存压力”的业务证据;回收结果也可能多于或少于请求值。

常见问题

memory.high 达到后会马上杀掉服务吗?

不会。它主要引入更重的回收和节流;真正的硬边界是 memory.max,也仍应结合事件和服务日志判断结果。

为什么 memory.events 和 memory.events.local 数字不一样?

memory.events 默认是层级统计,可能包含后代 cgroup;memory.events.local 只看当前 cgroup。服务拆分子组时应同时读取两者。

systemd 和手工写 memory.max 选哪个?

一次性定位问题可以手工写文件;长期服务优先使用 systemd 的 MemoryHigh、MemoryMax,让限制和 unit 生命周期一起管理。

最后用一张清单复查:控制器是否已向子层级开放、服务 PID 是否在目标 cgroup、high/max 是否符合工作集、events 是否按 local 与 hierarchy 分开解释。这样看到“回收事件增加”时,才能知道是在保护服务,还是已经撞上了硬边界。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
繁花动漫怎么选画质?高清、超高清与4K阅读说明繁花动漫怎么选画质?高清、超高清与4K阅读说明
上一篇
繁花动漫怎么选画质?高清、超高清与4K阅读说明
Go 文件权限 umask 与 Chmod 结果的关系
下一篇
Go 文件权限 umask 与 Chmod 结果的关系
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    316次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    374次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    370次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    336次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    162次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码