go.uber.org/ratelimit
package rlimit
import (
"fmt"
"log"
"testing"
"time"
"go.uber.org/ratelimit"
)
func TestRatelimit(t *testing.T) {
rl := ratelimit.New(5) // per second
log.Println("begin")
prev := time.Now()
for i := 0; i < 20; i++ {
now := rl.Take()
if i > 0 {
fmt.Println(time.Now().String(), i, now.Sub(prev))
}
prev = now
}
log.Println("end")
}
运行结果:
[@hbhly_x_128 rlimit]$ go test -v ./
=== RUN TestRatelimit
2022/03/26 16:57:41 begin
2022-03-26 16:57:42.014050639 +0800 CST m=+0.201108898 1 200ms
2022-03-26 16:57:42.21436404 +0800 CST m=+0.401422303 2 200ms
2022-03-26 16:57:42.415431893 +0800 CST m=+0.602490176 3 200ms
2022-03-26 16:57:42.613796177 +0800 CST m=+0.800854436 4 200ms
2022-03-26 16:57:42.813946371 +0800 CST m=+1.001004630 5 200ms
2022-03-26 16:57:43.014065797 +0800 CST m=+1.201124062 6 200ms
2022-03-26 16:57:43.213814857 +0800 CST m=+1.400873126 7 200ms
2022-03-26 16:57:43.414051201 +0800 CST m=+1.601109480 8 200ms
2022-03-26 16:57:43.614073789 +0800 CST m=+1.801132054 9 200ms
2022-03-26 16:57:43.815042061 +0800 CST m=+2.002100350 10 200ms
2022-03-26 16:57:44.013803537 +0800 CST m=+2.200861788 11 200ms
2022-03-26 16:57:44.213911271 +0800 CST m=+2.400969542 12 200ms
2022-03-26 16:57:44.413809965 +0800 CST m=+2.600868262 13 200ms
2022-03-26 16:57:44.613820171 +0800 CST m=+2.800878444 14 200ms
2022-03-26 16:57:44.813841891 +0800 CST m=+3.000900180 15 200ms
2022-03-26 16:57:45.013852437 +0800 CST m=+3.200910702 16 200ms
2022-03-26 16:57:45.213788735 +0800 CST m=+3.400846994 17 200ms
2022-03-26 16:57:45.414422254 +0800 CST m=+3.601480515 18 200ms
2022-03-26 16:57:45.613828739 +0800 CST m=+3.800887038 19 200ms
2022/03/26 16:57:45 end
--- PASS: TestRatelimit (3.80s)
PASS
ok demo/rlimit 3.805s
说明:New 函数限制了每秒的执行个数(5),所以每个请求间隔200ms,然后我们发现执行总个数(20)需要的时间(4s)
golang.org/x/time/rate
package rlimit
func TestRateLimiter(t *testing.T) {
// 第一个参数是r Limit。代表每秒可以向Token桶中产生多少token
// Limit实际上是float64的别名。
// 第二个参数是b int。b代表Token桶的容量大小。
//limiter := NewLimiter(10, 1);
// 除了直接指定每秒产生的Token个数外,还可以用Every方法来指定向Token桶中放置Token的间隔
// 例如:表示每100ms往桶中放一个Token。本质上也就是一秒钟产生10个:
limit := Every(100 * time.Millisecond);
limiter := NewLimiter(limit, 1);
}
github.com/go-redis/redis_rate/v9
package redis_rate_test
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
"github.com/go-redis/redis_rate/v9"
)
func ExampleNewLimiter() {
ctx := context.Background()
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
})
_ = rdb.FlushDB(ctx).Err()
limiter := redis_rate.NewLimiter(rdb)
res, err := limiter.Allow(ctx, "project:123", redis_rate.PerSecond(10))
if err != nil {
panic(err)
}
fmt.Println("allowed", res.Allowed, "remaining", res.Remaining)
// Output: allowed 1 remaining 9
}