go-redis/redis_rate 库实现了一个漏桶调度算法(又名通用信元速率算法)。
安装
1
|
go get github.com/go-redis/redis_rate/v10
|
使用
1
2
3
4
5
6
7
8
9
10
11
12
13
|
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
})
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
|
在 bunrouter 中使用 redis_rate 用于 HTTP 速率限制的中间件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
func rateLimit(next bunrouter.HandlerFunc) bunrouter.HandlerFunc {
return func(w http.ResponseWriter, req bunrouter.Request) error {
res, err := limiter.Allow(req.Context(), "project:123", redis_rate.PerMinute(10))
if err != nil {
return err
}
h := w.Header()
h.Set("RateLimit-Remaining", strconv.Itoa(res.Remaining))
if res.Allowed == 0 {
// We are rate limited.
seconds := int(res.RetryAfter / time.Second)
h.Set("RateLimit-RetryAfter", strconv.Itoa(seconds))
// Stop processing and return the error.
return ErrRateLimited
}
// Continue processing as normal.
return next(w, req)
}
}
|
参考