limit.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. package limit
  2. import (
  3. "errors"
  4. "os"
  5. "fmt"
  6. "io/ioutil"
  7. "strconv"
  8. )
  9. var (
  10. LimitConfNil = errors.New("Config of resource limit is nil")
  11. LimitConfError = errors.New("LimitConfError")
  12. CgroupPathNotExist = errors.New("Cgroup Path Not Exist")
  13. MemCgroupPathNotExist = errors.New("Mem subgroup Not Exist")
  14. CpuCgroupPathNotExist = errors.New("Cpu subgroup Not Exist")
  15. )
  16. type LimitConf struct {
  17. AppName string
  18. CgroupPath string
  19. LimitMemMB int
  20. LimitMemEnabled bool
  21. LimitCpuCore int
  22. LimitCpuEnabled bool
  23. }
  24. type Limit struct {
  25. c *LimitConf
  26. }
  27. // LimitRes init Limit
  28. func LimitRes(c *LimitConf) (l *Limit, err error) {
  29. if c == nil {
  30. return nil, LimitConfError
  31. }
  32. l = new(Limit)
  33. l.c = c
  34. if c.AppName == "" {
  35. return nil, fmt.Errorf("AppName can't be nil")
  36. }
  37. if err = pathExists(l.c.CgroupPath, false); err != nil {
  38. return nil, CgroupPathNotExist
  39. }
  40. if l.c.LimitMemEnabled {
  41. if l.c.LimitCpuCore <= 0 {
  42. return nil, fmt.Errorf("LimitCpuCore must be greater than 0")
  43. }
  44. if err = l.limitMem(); err != nil {
  45. return nil, err
  46. }
  47. }
  48. if l.c.LimitCpuEnabled {
  49. if l.c.LimitMemMB <= 0 {
  50. return nil, fmt.Errorf("LimitMemMB must be greater than 0")
  51. }
  52. if err = l.limitCpu(); err != nil {
  53. return nil, err
  54. }
  55. }
  56. return
  57. }
  58. // limitMem limit memory by memory.limit_in_bytes
  59. func (l *Limit) limitMem() (err error) {
  60. if err = pathExists(fmt.Sprintf("%s/memory", l.c.CgroupPath), false); err != nil {
  61. return MemCgroupPathNotExist
  62. }
  63. memPath := fmt.Sprintf("%s/memory/%s/", l.c.CgroupPath, l.c.AppName)
  64. if err = pathExists(memPath, true); err != nil {
  65. return err
  66. }
  67. // cgroup.procs
  68. pidPath := memPath + "cgroup.procs"
  69. if err = pathExists(pidPath, false); err != nil {
  70. return err
  71. }
  72. if err = ioutil.WriteFile(pidPath, []byte(strconv.Itoa(os.Getegid())), 0644); err != nil {
  73. return err
  74. }
  75. // memory.limit_in_bytes
  76. limitPath := memPath + "memory.limit_in_bytes"
  77. if err = pathExists(limitPath, false); err != nil {
  78. return err
  79. }
  80. if err = ioutil.WriteFile(limitPath, []byte(fmt.Sprintf("%sM", strconv.Itoa(l.c.LimitMemMB))), 0644); err != nil {
  81. return err
  82. }
  83. return
  84. }
  85. // limitCpu limit cpu by cpu.cfs_quota_us and cpu.cfs_period_us
  86. func (l *Limit) limitCpu() (err error) {
  87. if err = pathExists(fmt.Sprintf("%s/cpu,cpuacct", l.c.CgroupPath), false); err != nil {
  88. return CpuCgroupPathNotExist
  89. }
  90. cpuPath := fmt.Sprintf("%s/cpu,cpuacct/%s/", l.c.CgroupPath, l.c.AppName)
  91. if err = pathExists(cpuPath, true); err != nil {
  92. return err
  93. }
  94. // cpu.cfs_quota_us
  95. quotaPath := cpuPath + "cpu.cfs_quota_us"
  96. if err = pathExists(quotaPath, false); err != nil {
  97. return err
  98. }
  99. if err = ioutil.WriteFile(quotaPath, []byte(strconv.Itoa(10000)), 0644); err != nil {
  100. return err
  101. }
  102. // cpu.cfs_period_us
  103. periodPath := cpuPath + "cpu.cfs_period_us"
  104. if err = pathExists(periodPath, false); err != nil {
  105. return err
  106. }
  107. if err = ioutil.WriteFile(periodPath, []byte(fmt.Sprintf("%s", strconv.Itoa(10000*l.c.LimitCpuCore))), 0644); err != nil {
  108. return err
  109. }
  110. return
  111. }
  112. // pathExists check if path exist
  113. func pathExists(path string, create bool) (err error) {
  114. if _, err = os.Stat(path); err == nil {
  115. return
  116. }
  117. if os.IsNotExist(err) && create == true {
  118. return os.MkdirAll(path, os.ModePerm)
  119. }
  120. return
  121. }