token-bucket icon indicating copy to clipboard operation
token-bucket copied to clipboard

How to understand New(time.Second*1, 5)

Open nydw opened this issue 7 years ago • 0 comments

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()
	}

}()

nydw avatar Mar 20 '17 04:03 nydw