2
0

util.go 891 B

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. package main
  2. import (
  3. "net"
  4. "sync"
  5. "sync/atomic"
  6. "golang.org/x/time/rate"
  7. )
  8. const maxEntries = 10000 // Rotate when current map reaches this size (~2.5MB)
  9. var (
  10. current = &sync.Map{}
  11. previous = &sync.Map{}
  12. currentCount int64
  13. )
  14. func rateLimitAllow(addr string) bool {
  15. ip := addr
  16. if host, _, err := net.SplitHostPort(addr); err == nil {
  17. ip = host
  18. }
  19. if atomic.LoadInt64(&currentCount) >= maxEntries {
  20. rotate()
  21. }
  22. if val, ok := current.Load(ip); ok {
  23. return val.(*rate.Limiter).Allow()
  24. }
  25. if val, ok := previous.Load(ip); ok {
  26. current.Store(ip, val)
  27. atomic.AddInt64(&currentCount, 1)
  28. return val.(*rate.Limiter).Allow()
  29. }
  30. limiter := rate.NewLimiter(100.0/60, 10)
  31. current.Store(ip, limiter)
  32. atomic.AddInt64(&currentCount, 1)
  33. return limiter.Allow()
  34. }
  35. func rotate() {
  36. previous = current
  37. current = &sync.Map{}
  38. atomic.StoreInt64(&currentCount, 0)
  39. }