token-bucket
token-bucket copied to clipboard
How to understand New(time.Second*1, 5)
hi,
At first ,3ks for your codes. but I have some question.
How can I understand "New(time.Second1, 5)" ? I also read your codes " https://github.com/go-http-utils/ratelimit/blob/master/ratelimit.go", it start at the Line76. Is it mean than the new bucket can permit 5 tokens per second. 请问,我改怎么理解 New(time.Second1, 5) ? bucket 每秒发放5个token, 是这个意思吗 ?(here rewrite in Chinese, I just be sure that I can spell out my question.)
if it's that mean, Is my test case' output maybe something wrong ?
func TestTokenBucket(t *testing.T) { t.Run("Should return false when wait reach max duration", func(t testing.T) { b := New(time.Second1, 5) defer b.Destory() fmt.Println("1", time.Now().Unix()) b.Take(1) fmt.Println("2", time.Now().Unix()) b.Take(1) fmt.Println("3", time.Now().Unix()) b.Take(1) fmt.Println("4", time.Now().Unix()) b.Take(1) fmt.Println("5", time.Now().Unix()) b.Take(1) // time.Sleep(time.Second * 5) fmt.Println("6", time.Now().Unix()) b.Take(1) fmt.Println("7", time.Now().Unix()) b.Take(1) fmt.Println("8", time.Now().Unix()) b.Take(1) fmt.Println("9", time.Now().Unix()) b.Take(1) fmt.Println("0", time.Now().Unix()) }) }
OUTPUT:
1 1489984668 avail: 5 2 1489984668 avail: 4 3 1489984668 avail: 3 4 1489984668 avail: 2 5 1489984668 avail: 1
6 1489984668 avail: 0 7 1489984669 avail: 0 8 1489984670 avail: 0 9 1489984671 avail: 0 0 1489984672 PASS
func New(interval time.Duration, cap int64) *TokenBucket the first 5 times, it's nothing. but 6 7 8 one per second, generate one token per interval.
https://github.com/go-http-utils/ratelimit/blob/master/ratelimit.go:76
func Handler(h http.Handler, opts Options) http.Handler { if opts.GetID == nil { opts.GetID = defaultGetIDFunc } if opts.Duration == 0 { opts.Duration = time.Minute } if opts.Count == 0 { opts.Count = 1000 }
mutex := sync.Mutex{}
bucketsMap := map[string]*bucket.TokenBucket{}
expireMap := expireMap{}
interval := opts.Count / int64(opts.Duration/1e9) * 1e9
// Start a deamon gorouinue to check expiring.
// To take the performance into consideration, the deamon will
// only check at most 1000 buckets or cost at most one second at
// one tick.
go func() {
for now := range time.Tick(opts.Duration) {
mutex.Lock()
hasExpired := true
numExpired := 0
timeLimit := now.Add(time.Second)
for hasExpired && (numExpired < 1000 || now.After(timeLimit)) {
if id, ok := expireMap.getOneExpiredID(); ok {
delete(expireMap, id)
bucketsMap[id].Destory()
delete(bucketsMap, id)
numExpired++
} else {
hasExpired = false
}
}
mutex.Unlock()
}
}()