rate_limiter.go 1.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. package tos
  2. import (
  3. "sync"
  4. "time"
  5. )
  6. const (
  7. minRate = 1024
  8. minCapacity = 10 * 1024
  9. )
  10. type defaultRateLimit struct {
  11. rate int64
  12. capacity int64
  13. currentAmount int64
  14. sync.Mutex
  15. lastConsumeTime time.Time
  16. }
  17. func NewDefaultRateLimit(rate int64, capacity int64) RateLimiter {
  18. if rate < minRate {
  19. rate = minRate
  20. }
  21. if capacity < minCapacity {
  22. capacity = minCapacity
  23. }
  24. return &defaultRateLimit{
  25. rate: rate,
  26. capacity: capacity,
  27. lastConsumeTime: time.Now(),
  28. currentAmount: capacity,
  29. Mutex: sync.Mutex{},
  30. }
  31. }
  32. func (d *defaultRateLimit) Acquire(want int64) (ok bool, timeToWait time.Duration) {
  33. d.Lock()
  34. defer d.Unlock()
  35. if want > d.capacity {
  36. want = d.capacity
  37. }
  38. increment := int64(time.Since(d.lastConsumeTime).Seconds() * float64(d.rate))
  39. if increment+d.currentAmount > d.capacity {
  40. d.currentAmount = d.capacity
  41. } else {
  42. d.currentAmount += increment
  43. }
  44. if want > d.currentAmount {
  45. timeToWaitSec := float64(want-d.currentAmount) / float64(d.rate)
  46. return false, time.Duration(timeToWaitSec * float64(time.Second))
  47. }
  48. d.lastConsumeTime = time.Now()
  49. d.currentAmount -= want
  50. return true, 0
  51. }