Golang的滑动窗口计数器Redis限速实现

21-11-23 banq

这是一个基于Figma 工程团队的博客文章构建的简单速率限制器。

有关实际算法的要求和设计的信息,请参阅帖子。

限速器满足这个接口:

type  Limiter  interface {
     Increment (context. Context , string , int ) error 
}

该实现由 Redis 支持并使用 go-redis 库。

client := goredis.NewClient(&goredis.Options{
    Addr: "localhost:6379",
})

ratelimiter := redis.New(client, 10, time.Minute, time.Hour)

ratelimiter.Increment(ctx, "user_id", 1)

为方便起见,还有一个 http 中间件。灵感来自 Seth Vargo 的速率限制库:

ratelimiter := redis.New(client, 10, time.Minute, time.Hour)
mw := ratelimit.Middleware(ratelimiter, ratelimit.IPKeyFunc, 1)
// use mw in your favourite HTTP library

Middleware函数有一个weight参数,它允许您为某些路由提供更高的增量权重。例如,您的基本速率限制可以是每小时 1000 个请求,每个请求的权重为 1,但计算量特别大的端点可能希望权重为 10,因此每个请求将内部计数器增加 10 而不是 1 .

如果您使用多个中间件实例,请确保不要向全局多路复用器/路由器添加一个,否则您的请求将触发两个速率限制计算(因此,Redis 网络 I/O 操作)。这可以在未来通过集中式中间件控制器来解决,该控制器提供具有优先级规则顺序等的限制器树。

源码查看 Github

1
猜你喜欢