limit.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. package rate
  2. import (
  3. "net/http"
  4. "sync/atomic"
  5. "go-common/library/log"
  6. bm "go-common/library/net/http/blademaster"
  7. "golang.org/x/time/rate"
  8. )
  9. const (
  10. _defBurst = 100
  11. )
  12. // Limiter controls how frequently events are allowed to happen.
  13. type Limiter struct {
  14. apps atomic.Value
  15. urls atomic.Value
  16. }
  17. // Config limitter conf.
  18. type Config struct {
  19. Apps map[string]*Limit
  20. URLs map[string]*Limit
  21. }
  22. // Limit limit conf.
  23. type Limit struct {
  24. Limit rate.Limit
  25. Burst int
  26. }
  27. // New return Limiter.
  28. func New(conf *Config) (l *Limiter) {
  29. l = &Limiter{}
  30. l.apps.Store(make(map[string]*rate.Limiter))
  31. l.urls.Store(make(map[string]*rate.Limiter))
  32. if conf != nil {
  33. l.Reload(conf)
  34. }
  35. return
  36. }
  37. // Reload reload limit conf.
  38. func (l *Limiter) Reload(c *Config) {
  39. if c == nil {
  40. return
  41. }
  42. var (
  43. ok bool
  44. al *rate.Limiter
  45. ul *rate.Limiter
  46. as map[string]*rate.Limiter
  47. nas map[string]*rate.Limiter
  48. us map[string]*rate.Limiter
  49. nus map[string]*rate.Limiter
  50. )
  51. if as, ok = l.apps.Load().(map[string]*rate.Limiter); !ok {
  52. log.Error("apps limiter load map hava no data ")
  53. return
  54. }
  55. nas = make(map[string]*rate.Limiter, len(as))
  56. for k, v := range as {
  57. nas[k] = v
  58. }
  59. for k, v := range c.Apps {
  60. if al, ok = nas[k]; !ok || (al.Burst() != v.Burst || al.Limit() != v.Limit) {
  61. nas[k] = rate.NewLimiter(v.fix())
  62. }
  63. }
  64. l.apps.Store(nas)
  65. if us, ok = l.urls.Load().(map[string]*rate.Limiter); !ok {
  66. log.Error("urls limiter load map hava no data ")
  67. return
  68. }
  69. nus = make(map[string]*rate.Limiter, len(us))
  70. for k, v := range us {
  71. nus[k] = v
  72. }
  73. for k, v := range c.URLs {
  74. if ul, ok = nus[k]; !ok || (ul.Burst() != v.Burst || ul.Limit() != v.Limit) {
  75. nus[k] = rate.NewLimiter(v.fix())
  76. }
  77. }
  78. l.urls.Store(nus)
  79. }
  80. func (l *Limit) fix() (lim rate.Limit, b int) {
  81. lim = rate.Inf
  82. b = _defBurst
  83. if l.Limit <= 0 {
  84. lim = rate.Inf
  85. } else {
  86. lim = l.Limit
  87. }
  88. if l.Burst > 0 {
  89. b = l.Burst
  90. }
  91. return
  92. }
  93. // Allow reports whether event may happen at time now.
  94. func (l *Limiter) Allow(appKey, path string) bool {
  95. if as, ok := l.apps.Load().(map[string]*rate.Limiter); ok {
  96. if lim, ok := as[appKey]; ok {
  97. if !lim.Allow() {
  98. return false
  99. }
  100. }
  101. }
  102. if us, ok := l.urls.Load().(map[string]*rate.Limiter); ok {
  103. if lim, ok := us[path]; ok {
  104. if !lim.Allow() {
  105. return false
  106. }
  107. }
  108. }
  109. return true
  110. }
  111. func (l *Limiter) ServeHTTP(c *bm.Context) {
  112. req := c.Request
  113. appkey := req.Form.Get("appkey")
  114. path := req.URL.Path
  115. if !l.Allow(appkey, path) {
  116. c.AbortWithStatus(http.StatusTooManyRequests)
  117. return
  118. }
  119. }
  120. // Handler is router allow handle.
  121. func (l *Limiter) Handler() bm.HandlerFunc {
  122. return l.ServeHTTP
  123. }