mirror of https://github.com/q191201771/naza
[feat] package ratelimit: 新增漏桶LeakyBucket和令牌桶TokenBucket,把以前的RateLimit删了
parent
0012c33084
commit
637a4d066a
@ -0,0 +1,124 @@
|
||||
// Copyright 2020, Chef. All rights reserved.
|
||||
// https://github.com/q191201771/naza
|
||||
//
|
||||
// Use of this source code is governed by a MIT-style license
|
||||
// that can be found in the License file.
|
||||
//
|
||||
// Author: Chef (191201771@qq.com)
|
||||
|
||||
package ratelimit_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/q191201771/naza/pkg/nazalog"
|
||||
"github.com/q191201771/naza/pkg/ratelimit"
|
||||
)
|
||||
|
||||
var runExample = true
|
||||
|
||||
func TestLeakyBucket(t *testing.T) {
|
||||
if !runExample {
|
||||
return
|
||||
}
|
||||
|
||||
lb := ratelimit.NewLeakyBucket(100)
|
||||
for i := 0; i < 16; i++ {
|
||||
go func(j int) {
|
||||
for k := 0; k < 16; k++ {
|
||||
err := lb.TryAquire()
|
||||
if err == nil {
|
||||
nazalog.Debugf("TryAquire succ. goroutine=%d, index=%d", j, k)
|
||||
} else {
|
||||
//nazalog.Debugf("TryAquire fail. goroutine=%d, index=%d, err=%v", j, k, err)
|
||||
time.Sleep(time.Duration(j*k) * time.Millisecond)
|
||||
}
|
||||
//time.Sleep(time.Duration(j * k) * time.Millisecond)
|
||||
}
|
||||
}(i)
|
||||
}
|
||||
time.Sleep(2 * time.Second)
|
||||
//2020/02/25 23:39:13.896802 DEBUG TryAquire succ. goroutine=10, index=5 - example_test.go:23
|
||||
//2020/02/25 23:39:13.999801 DEBUG TryAquire succ. goroutine=7, index=8 - example_test.go:23
|
||||
//2020/02/25 23:39:14.113313 DEBUG TryAquire succ. goroutine=11, index=8 - example_test.go:23
|
||||
//2020/02/25 23:39:14.216280 DEBUG TryAquire succ. goroutine=11, index=10 - example_test.go:23
|
||||
//2020/02/25 23:39:14.334289 DEBUG TryAquire succ. goroutine=8, index=12 - example_test.go:23
|
||||
//2020/02/25 23:39:14.439413 DEBUG TryAquire succ. goroutine=8, index=14 - example_test.go:23
|
||||
//2020/02/25 23:39:14.574673 DEBUG TryAquire succ. goroutine=14, index=11 - example_test.go:23
|
||||
//2020/02/25 23:39:14.742899 DEBUG TryAquire succ. goroutine=14, index=13 - example_test.go:23
|
||||
//2020/02/25 23:39:14.914085 DEBUG TryAquire succ. goroutine=12, index=14 - example_test.go:23
|
||||
//2020/02/25 23:39:15.172121 DEBUG TryAquire succ. goroutine=15, index=14 - example_test.go:23
|
||||
|
||||
lb2 := ratelimit.NewLeakyBucket(100)
|
||||
for i := 0; i < 4; i++ {
|
||||
go func(j int) {
|
||||
for k := 0; k < 4; k++ {
|
||||
lb2.WaitUntilAquire()
|
||||
nazalog.Debugf("< lb.WaitUntilAquire. goroutine=%d, index=%d", j, k)
|
||||
}
|
||||
}(i)
|
||||
}
|
||||
time.Sleep(2 * time.Second)
|
||||
//2020/02/25 23:40:11.275685 DEBUG < lb.WaitUntilAquire. goroutine=3, index=0 - example_test.go:49
|
||||
//2020/02/25 23:40:11.374789 DEBUG < lb.WaitUntilAquire. goroutine=0, index=0 - example_test.go:49
|
||||
//2020/02/25 23:40:11.473445 DEBUG < lb.WaitUntilAquire. goroutine=1, index=0 - example_test.go:49
|
||||
//2020/02/25 23:40:11.571714 DEBUG < lb.WaitUntilAquire. goroutine=2, index=0 - example_test.go:49
|
||||
//2020/02/25 23:40:11.670913 DEBUG < lb.WaitUntilAquire. goroutine=3, index=1 - example_test.go:49
|
||||
//2020/02/25 23:40:11.772003 DEBUG < lb.WaitUntilAquire. goroutine=0, index=1 - example_test.go:49
|
||||
//2020/02/25 23:40:11.871239 DEBUG < lb.WaitUntilAquire. goroutine=1, index=1 - example_test.go:49
|
||||
//2020/02/25 23:40:11.973307 DEBUG < lb.WaitUntilAquire. goroutine=2, index=1 - example_test.go:49
|
||||
//2020/02/25 23:40:12.075015 DEBUG < lb.WaitUntilAquire. goroutine=3, index=2 - example_test.go:49
|
||||
//2020/02/25 23:40:12.173357 DEBUG < lb.WaitUntilAquire. goroutine=0, index=2 - example_test.go:49
|
||||
//2020/02/25 23:40:12.270387 DEBUG < lb.WaitUntilAquire. goroutine=1, index=2 - example_test.go:49
|
||||
//2020/02/25 23:40:12.370509 DEBUG < lb.WaitUntilAquire. goroutine=2, index=2 - example_test.go:49
|
||||
//2020/02/25 23:40:12.475001 DEBUG < lb.WaitUntilAquire. goroutine=3, index=3 - example_test.go:49
|
||||
//2020/02/25 23:40:12.571062 DEBUG < lb.WaitUntilAquire. goroutine=0, index=3 - example_test.go:49
|
||||
//2020/02/25 18:40:12.672385 DEBUG < lb.WaitUntilAquire. goroutine=1, index=3 - example_test.go:49
|
||||
//2020/02/25 18:40:12.770939 DEBUG < lb.WaitUntilAquire. goroutine=2, index=3 - example_test.go:49
|
||||
}
|
||||
|
||||
func TestTokenBucket(t *testing.T) {
|
||||
if !runExample {
|
||||
return
|
||||
}
|
||||
|
||||
tb := ratelimit.NewTokenBucket(100, 1000, 10)
|
||||
for i := 0; i < 4; i++ {
|
||||
go func(j int) {
|
||||
for k := 0; k < 4; k++ {
|
||||
tb.WaitUntilAquire()
|
||||
nazalog.Debugf("< tb.WaitUntilAquire. goroutine=%d, index=%d", j, k)
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
}(i)
|
||||
}
|
||||
time.Sleep(2 * time.Second)
|
||||
//2020/02/25 19:02:33.453207 DEBUG < tb.WaitUntilAquire. goroutine=2, index=0 - example_test.go:82
|
||||
//2020/02/25 19:02:33.453302 DEBUG < tb.WaitUntilAquire. goroutine=1, index=0 - example_test.go:82
|
||||
//2020/02/25 19:02:33.453414 DEBUG < tb.WaitUntilAquire. goroutine=0, index=0 - example_test.go:82
|
||||
//2020/02/25 19:02:33.453535 DEBUG < tb.WaitUntilAquire. goroutine=3, index=0 - example_test.go:82
|
||||
//2020/02/25 19:02:33.557602 DEBUG < tb.WaitUntilAquire. goroutine=2, index=1 - example_test.go:82
|
||||
//2020/02/25 19:02:33.557881 DEBUG < tb.WaitUntilAquire. goroutine=0, index=1 - example_test.go:82
|
||||
//2020/02/25 19:02:33.557968 DEBUG < tb.WaitUntilAquire. goroutine=1, index=1 - example_test.go:82
|
||||
//2020/02/25 19:02:33.558043 DEBUG < tb.WaitUntilAquire. goroutine=3, index=1 - example_test.go:82
|
||||
//2020/02/25 19:02:33.661411 DEBUG < tb.WaitUntilAquire. goroutine=0, index=2 - example_test.go:82
|
||||
//2020/02/25 19:02:33.661495 DEBUG < tb.WaitUntilAquire. goroutine=2, index=2 - example_test.go:82
|
||||
//2020/02/25 19:02:34.451624 DEBUG < tb.WaitUntilAquire. goroutine=2, index=3 - example_test.go:82
|
||||
//2020/02/25 19:02:34.451715 DEBUG < tb.WaitUntilAquire. goroutine=0, index=3 - example_test.go:82
|
||||
//2020/02/25 19:02:34.451787 DEBUG < tb.WaitUntilAquire. goroutine=3, index=2 - example_test.go:82
|
||||
//2020/02/25 19:02:34.451841 DEBUG < tb.WaitUntilAquire. goroutine=1, index=2 - example_test.go:82
|
||||
//2020/02/25 19:02:34.551910 DEBUG < tb.WaitUntilAquire. goroutine=3, index=3 - example_test.go:82
|
||||
//2020/02/25 19:02:34.556604 DEBUG < tb.WaitUntilAquire. goroutine=1, index=3 - example_test.go:82
|
||||
|
||||
}
|
||||
|
||||
func TestRateLimiter(t *testing.T) {
|
||||
tb := ratelimit.NewTokenBucket(1, 1, 1)
|
||||
lb := ratelimit.NewLeakyBucket(1)
|
||||
var rl ratelimit.RateLimiter
|
||||
rl = tb
|
||||
rl.WaitUntilAquire()
|
||||
rl = lb
|
||||
rl.TryAquire()
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
// Copyright 2020, Chef. All rights reserved.
|
||||
// https://github.com/q191201771/naza
|
||||
//
|
||||
// Use of this source code is governed by a MIT-style license
|
||||
// that can be found in the License file.
|
||||
//
|
||||
// Author: Chef (191201771@qq.com)
|
||||
|
||||
package ratelimit_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/q191201771/naza/pkg/assert"
|
||||
"github.com/q191201771/naza/pkg/ratelimit"
|
||||
)
|
||||
|
||||
func TestNewLeakyBucket(t *testing.T) {
|
||||
ratelimit.NewLeakyBucket(10)
|
||||
}
|
||||
|
||||
func TestLeakyBucket_TryAquire(t *testing.T) {
|
||||
var (
|
||||
lb *ratelimit.LeakyBucket
|
||||
err error
|
||||
)
|
||||
|
||||
lb = ratelimit.NewLeakyBucket(1)
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
err = lb.TryAquire()
|
||||
assert.Equal(t, nil, err)
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
err = lb.TryAquire()
|
||||
assert.Equal(t, nil, err)
|
||||
|
||||
lb = ratelimit.NewLeakyBucket(100)
|
||||
err = lb.TryAquire()
|
||||
assert.Equal(t, ratelimit.ErrResourceNotAvailable, err)
|
||||
err = lb.TryAquire()
|
||||
assert.Equal(t, ratelimit.ErrResourceNotAvailable, err)
|
||||
}
|
||||
|
||||
func TestLeakyBucket_WaitUntilAquire(t *testing.T) {
|
||||
var lb *ratelimit.LeakyBucket
|
||||
|
||||
lb = ratelimit.NewLeakyBucket(1)
|
||||
lb.WaitUntilAquire()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
lb.WaitUntilAquire()
|
||||
|
||||
lb = ratelimit.NewLeakyBucket(200)
|
||||
lb.WaitUntilAquire()
|
||||
lb.WaitUntilAquire()
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
// Copyright 2019, Chef. All rights reserved.
|
||||
// https://github.com/q191201771/naza
|
||||
//
|
||||
// Use of this source code is governed by a MIT-style license
|
||||
// that can be found in the License file.
|
||||
//
|
||||
// Author: Chef (191201771@qq.com)
|
||||
|
||||
package ratelimit_test
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/q191201771/naza/pkg/nazalog"
|
||||
"github.com/q191201771/naza/pkg/ratelimit"
|
||||
)
|
||||
|
||||
var (
|
||||
duration = 100 * time.Millisecond
|
||||
num = 50
|
||||
)
|
||||
|
||||
func TestNew(t *testing.T) {
|
||||
rl := ratelimit.New(num)
|
||||
rl = ratelimit.New(num, func(option *ratelimit.Option) {
|
||||
option.Duration = duration
|
||||
})
|
||||
rl.Wait()
|
||||
}
|
||||
|
||||
func TestRateLimit_Wait(t *testing.T) {
|
||||
rl := ratelimit.New(num, func(option *ratelimit.Option) {
|
||||
option.Duration = duration
|
||||
})
|
||||
b := time.Now()
|
||||
for i := 0; i < num; i++ {
|
||||
rl.Wait()
|
||||
}
|
||||
nazalog.Debugf("cost:%v", time.Now().Sub(b))
|
||||
}
|
||||
|
||||
func TestRateLimit_Wait2(t *testing.T) {
|
||||
rl := ratelimit.New(num, func(option *ratelimit.Option) {
|
||||
option.Duration = duration
|
||||
})
|
||||
b := time.Now()
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(num)
|
||||
for i := 0; i < num; i++ {
|
||||
go func(ii int) {
|
||||
rl.Wait()
|
||||
wg.Done()
|
||||
}(i)
|
||||
}
|
||||
wg.Wait()
|
||||
nazalog.Debugf("cost:%v", time.Now().Sub(b))
|
||||
}
|
||||
|
||||
func TestRateLimit_Wait3(t *testing.T) {
|
||||
rand.Seed(time.Now().Unix())
|
||||
rl := ratelimit.New(num, func(option *ratelimit.Option) {
|
||||
option.Duration = duration
|
||||
})
|
||||
b := time.Now()
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(num)
|
||||
for i := 0; i < num; i++ {
|
||||
go func(ii int) {
|
||||
time.Sleep(time.Duration(rand.Int63n(int64(duration) / 2)))
|
||||
rl.Wait()
|
||||
wg.Done()
|
||||
}(i)
|
||||
}
|
||||
wg.Wait()
|
||||
nazalog.Debugf("cost:%v", time.Now().Sub(b))
|
||||
}
|
||||
|
||||
func TestRateLimit_Wait4(t *testing.T) {
|
||||
rl := ratelimit.New(num, func(option *ratelimit.Option) {
|
||||
option.Duration = duration
|
||||
})
|
||||
b := time.Now()
|
||||
for i := 0; i < num; i++ {
|
||||
time.Sleep(time.Duration(int64(duration) * 2 / int64(num)))
|
||||
rl.Wait()
|
||||
}
|
||||
nazalog.Debugf("cost:%v", time.Now().Sub(b))
|
||||
}
|
||||
|
||||
func BenchmarkRateLimit_Wait(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
rl := ratelimit.New(num)
|
||||
for i := 0; i < num; i++ {
|
||||
rl.Wait()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
// Copyright 2020, Chef. All rights reserved.
|
||||
// https://github.com/q191201771/naza
|
||||
//
|
||||
// Use of this source code is governed by a MIT-style license
|
||||
// that can be found in the License file.
|
||||
//
|
||||
// Author: Chef (191201771@qq.com)
|
||||
|
||||
package ratelimit_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/q191201771/naza/pkg/assert"
|
||||
"github.com/q191201771/naza/pkg/nazalog"
|
||||
"github.com/q191201771/naza/pkg/ratelimit"
|
||||
)
|
||||
|
||||
func TestNewTokenBucket(t *testing.T) {
|
||||
ratelimit.NewTokenBucket(2000, 1000, 1000)
|
||||
}
|
||||
|
||||
func TestTokenBucket_TryAquire(t *testing.T) {
|
||||
var (
|
||||
tb *ratelimit.TokenBucket
|
||||
err error
|
||||
)
|
||||
|
||||
tb = ratelimit.NewTokenBucket(2000, 1000, 1000)
|
||||
err = tb.TryAquire()
|
||||
assert.Equal(t, ratelimit.ErrTokenNotEnough, err)
|
||||
err = tb.TryAquire()
|
||||
assert.Equal(t, ratelimit.ErrTokenNotEnough, err)
|
||||
|
||||
tb = ratelimit.NewTokenBucket(2000, 1, 1000)
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
err = tb.TryAquire()
|
||||
assert.Equal(t, nil, err)
|
||||
err = tb.TryAquire()
|
||||
assert.Equal(t, nil, err)
|
||||
}
|
||||
|
||||
func TestTokenBucket_WaitUntilAquire(t *testing.T) {
|
||||
var tb *ratelimit.TokenBucket
|
||||
|
||||
tb = ratelimit.NewTokenBucket(2000, 1000, 1000)
|
||||
tb.WaitUntilAquire()
|
||||
tb.WaitUntilAquire()
|
||||
}
|
||||
|
||||
func TestTokenBucket_Dispose(t *testing.T) {
|
||||
var (
|
||||
tb *ratelimit.TokenBucket
|
||||
err error
|
||||
)
|
||||
|
||||
tb = ratelimit.NewTokenBucket(2000, 1, 1000)
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
err = tb.TryAquireWithNum(1)
|
||||
assert.Equal(t, nil, err)
|
||||
tb.WaitUntilAquireWithNum(1)
|
||||
tb.Dispose()
|
||||
}
|
||||
|
||||
func TestTokenBucket_panic(t *testing.T) {
|
||||
defer func() {
|
||||
nazalog.Debug(recover())
|
||||
}()
|
||||
tb := ratelimit.NewTokenBucket(1, 1, 1)
|
||||
tb.TryAquireWithNum(100)
|
||||
}
|
Loading…
Reference in New Issue