123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- package limit
- import (
- "errors"
- "os"
- "fmt"
- "io/ioutil"
- "strconv"
- )
- var (
- LimitConfNil = errors.New("Config of resource limit is nil")
- LimitConfError = errors.New("LimitConfError")
- CgroupPathNotExist = errors.New("Cgroup Path Not Exist")
- MemCgroupPathNotExist = errors.New("Mem subgroup Not Exist")
- CpuCgroupPathNotExist = errors.New("Cpu subgroup Not Exist")
- )
- type LimitConf struct {
- AppName string
- CgroupPath string
- LimitMemMB int
- LimitMemEnabled bool
- LimitCpuCore int
- LimitCpuEnabled bool
- }
- type Limit struct {
- c *LimitConf
- }
- // LimitRes init Limit
- func LimitRes(c *LimitConf) (l *Limit, err error) {
- if c == nil {
- return nil, LimitConfError
- }
- l = new(Limit)
- l.c = c
- if c.AppName == "" {
- return nil, fmt.Errorf("AppName can't be nil")
- }
- if err = pathExists(l.c.CgroupPath, false); err != nil {
- return nil, CgroupPathNotExist
- }
- if l.c.LimitMemEnabled {
- if l.c.LimitCpuCore <= 0 {
- return nil, fmt.Errorf("LimitCpuCore must be greater than 0")
- }
- if err = l.limitMem(); err != nil {
- return nil, err
- }
- }
- if l.c.LimitCpuEnabled {
- if l.c.LimitMemMB <= 0 {
- return nil, fmt.Errorf("LimitMemMB must be greater than 0")
- }
- if err = l.limitCpu(); err != nil {
- return nil, err
- }
- }
- return
- }
- // limitMem limit memory by memory.limit_in_bytes
- func (l *Limit) limitMem() (err error) {
- if err = pathExists(fmt.Sprintf("%s/memory", l.c.CgroupPath), false); err != nil {
- return MemCgroupPathNotExist
- }
- memPath := fmt.Sprintf("%s/memory/%s/", l.c.CgroupPath, l.c.AppName)
- if err = pathExists(memPath, true); err != nil {
- return err
- }
- // cgroup.procs
- pidPath := memPath + "cgroup.procs"
- if err = pathExists(pidPath, false); err != nil {
- return err
- }
- if err = ioutil.WriteFile(pidPath, []byte(strconv.Itoa(os.Getegid())), 0644); err != nil {
- return err
- }
- // memory.limit_in_bytes
- limitPath := memPath + "memory.limit_in_bytes"
- if err = pathExists(limitPath, false); err != nil {
- return err
- }
- if err = ioutil.WriteFile(limitPath, []byte(fmt.Sprintf("%sM", strconv.Itoa(l.c.LimitMemMB))), 0644); err != nil {
- return err
- }
- return
- }
- // limitCpu limit cpu by cpu.cfs_quota_us and cpu.cfs_period_us
- func (l *Limit) limitCpu() (err error) {
- if err = pathExists(fmt.Sprintf("%s/cpu,cpuacct", l.c.CgroupPath), false); err != nil {
- return CpuCgroupPathNotExist
- }
- cpuPath := fmt.Sprintf("%s/cpu,cpuacct/%s/", l.c.CgroupPath, l.c.AppName)
- if err = pathExists(cpuPath, true); err != nil {
- return err
- }
- // cpu.cfs_quota_us
- quotaPath := cpuPath + "cpu.cfs_quota_us"
- if err = pathExists(quotaPath, false); err != nil {
- return err
- }
- if err = ioutil.WriteFile(quotaPath, []byte(strconv.Itoa(10000)), 0644); err != nil {
- return err
- }
- // cpu.cfs_period_us
- periodPath := cpuPath + "cpu.cfs_period_us"
- if err = pathExists(periodPath, false); err != nil {
- return err
- }
- if err = ioutil.WriteFile(periodPath, []byte(fmt.Sprintf("%s", strconv.Itoa(10000*l.c.LimitCpuCore))), 0644); err != nil {
- return err
- }
- return
- }
- // pathExists check if path exist
- func pathExists(path string, create bool) (err error) {
- if _, err = os.Stat(path); err == nil {
- return
- }
- if os.IsNotExist(err) && create == true {
- return os.MkdirAll(path, os.ModePerm)
- }
- return
- }
|