[Go] 使用 CGroup 实现进程内存控制
Contents
使用 CGroup 实现进程内存控制
背景
从 Linux 内核 2.6.25 开始,CGroup 支持对进程内存的隔离和限制,这也是 Docker 等容器技术的底层支撑。
使用 CGroup 有如下好处
在共享的机器上,进程相互隔离,互不影响,对其它进程是种保护。 对于存在内存泄漏的进程,可以设置内存限制,通过系统 OOM 触发的 Kill 信号量来实现重启。
Linux 系统默认支持 CGroup, 而且默认挂载所有选项,可以使用 mount -t cgroup 来查看:
$ mount -t cgroup
cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd)
cgroup on /sys/fs/cgroup/net_cls type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls)
cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset)
cgroup on /sys/fs/cgroup/perf_event type cgroup (rw,nosuid,nodev,noexec,relatime,perf_event)
cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer)
cgroup on /sys/fs/cgroup/memory type cgroup (rw,nosuid,nodev,noexec,relatime,memory)
cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpuacct,cpu)
cgroup on /sys/fs/cgroup/hugetlb type cgroup (rw,nosuid,nodev,noexec,relatime,hugetlb)
cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices)
cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio)
以内存为例,创建 climits 内存分组
使用 mkdir /sys/fs/cgroup/memory/climits 来创建属于自己的内存组 climits
$ mkdir /sys/fs/cgroup/memory/climits
此时系统已经在目录 /sys/fs/cgroup/memory/climits 下生成内存相关的所有配置
$ ls -la /sys/fs/cgroup/memory/climits
cgroup.clone_children memory.kmem.limit_in_bytes memory.kmem.tcp.usage_in_bytes memory.memsw.max_usage_in_bytes memory.soft_limit_in_bytes tasks
cgroup.event_control memory.kmem.max_usage_in_bytes memory.kmem.usage_in_bytes memory.memsw.usage_in_bytes memory.stat
cgroup.procs memory.kmem.slabinfo memory.limit_in_bytes memory.move_charge_at_immigrate memory.swappiness
memory.failcnt memory.kmem.tcp.failcnt memory.max_usage_in_bytes memory.numa_stat memory.usage_in_bytes
memory.force_empty memory.kmem.tcp.limit_in_bytes memory.memsw.failcnt memory.oom_control memory.use_hierarchy
memory.kmem.failcnt memory.kmem.tcp.max_usage_in_bytes memory.memsw.limit_in_bytes memory.pressure_level notify_on_release
主要配置含义:
- cgroup.procs: 使用该组配置的进程列表。
- memory.limit_in_bytes:内存使用限制。
- memory.memsw.limit_in_bytes:内存和交换分区总计限制。
- memory.swappiness: 交换分区使用比例。
- memory.usage_in_bytes: 当前进程内存使用量。
- memory.stat: 内存使用统计信息。
- memory.oom_control: OOM 控制参数。
设置内存限制
假设有进程 pid 1234,设置内存限制为 10MB,可以这样操作:
limit_in_bytes 设置为 10MB
echo 10M > /sys/fs/cgroup/memory/climits/memory.limit_in_bytes
swappiness 设置为 0,表示禁用交换分区,实际生产中可以配置合适的比例。
echo 0 > /sys/fs/cgroup/memory/climits/memory.swappiness
添加控制进程
echo 1234 > /sys/fs/cgroup/memory/climits/cgroup.procs
当进程 1234 使用内存超过 10MB 的时候,默认进程 1234 会触发 OOM,被系统 Kill 掉。
Go 实现进程内存限制
用 Go 代码来实现一个简单的进程内存限制以及守护(被 Kill 能够自动重启)
- 进程测试代码 每隔一秒申请 1MB 存储空间,并且不释放,然后再打印下 Go 的内存申请情况
|
|
通过 GOOS=linux GOARCH=amd64 go build -o simpleapp example/simple_app.go 命令,编译一个 Linux 版本的可执行程序 simpleapp。
- 进程守护程序 该守护程序主要实现进程内存限制和进程守护(自动重启)
|
|