go - 使用 golang.org/x/time/rate 每分钟允许 N 个请求

标签 go rate-limiting

我想要什么:
每分钟允许 n 个请求的限制器。

我尝试过的:

(somewhere during init procedure)

limiter = rate.NewLimiter(rate.Every(1*time.Minute/2), 2)

然后在我的 HTTP 服务器的中间件中:

func (self *Router) limiterMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(responseWriter http.ResponseWriter, request *http.Request) {
        if !limiter.Allow(){
            http.Error(responseWriter, "Too many requests", http.StatusTooManyRequests)
            return
        }

        next.ServeHTTP(responseWriter, request)
    })
}

据我了解,这应该每分钟允许 2 个请求。然后我尝试发送几个请求,前两个请求之间有 15 秒的暂停,然后大约每秒 1 个请求。

期望:

  • 前两个请求有效
  • 后续请求将获取 HTTP429,直到 1 分钟过去,第一个后续请求将被“清除”
  • 还有一个请求有效
  • 后续请求获取 HTTP429,直到 15 秒已通过,并且最初的第二个请求被“清除”

实际结果:

22/10/31 14:02:31 access: 200 POST /some/path
22/10/31 14:02:46 access: 200 POST /some/path
22/10/31 14:02:47 access: 429 POST /some/path
22/10/31 14:02:48 access: 429 POST /some/path
22/10/31 14:02:49 access: 429 POST /some/path
22/10/31 14:02:50 access: 429 POST /some/path
22/10/31 14:02:51 access: 429 POST /some/path
22/10/31 14:02:52 access: 429 POST /some/path
22/10/31 14:02:53 access: 429 POST /some/path
22/10/31 14:02:54 access: 429 POST /some/path
22/10/31 14:02:55 access: 429 POST /some/path
22/10/31 14:02:56 access: 429 POST /some/path
22/10/31 14:02:57 access: 429 POST /some/path
22/10/31 14:02:58 access: 429 POST /some/path
22/10/31 14:02:59 access: 429 POST /some/path
22/10/31 14:03:00 access: 429 POST /some/path
22/10/31 14:03:01 access: 200 POST /some/path
22/10/31 14:03:02 access: 429 POST /some/path
22/10/31 14:03:03 access: 429 POST /some/path
22/10/31 14:03:04 access: 429 POST /some/path
22/10/31 14:03:05 access: 429 POST /some/path
22/10/31 14:03:06 access: 429 POST /some/path
22/10/31 14:03:07 access: 429 POST /some/path
22/10/31 14:03:08 access: 429 POST /some/path
22/10/31 14:03:09 access: 429 POST /some/path
22/10/31 14:03:10 access: 429 POST /some/path
22/10/31 14:03:11 access: 429 POST /some/path
22/10/31 14:03:12 access: 429 POST /some/path
22/10/31 14:03:13 access: 429 POST /some/path
22/10/31 14:03:14 access: 429 POST /some/path
22/10/31 14:03:15 access: 429 POST /some/path
22/10/31 14:03:16 access: 429 POST /some/path
22/10/31 14:03:16 access: 429 POST /some/path
22/10/31 14:03:17 access: 429 POST /some/path
22/10/31 14:03:18 access: 429 POST /some/path
22/10/31 14:03:19 access: 429 POST /some/path
22/10/31 14:03:20 access: 429 POST /some/path
22/10/31 14:03:21 access: 429 POST /some/path
22/10/31 14:03:22 access: 429 POST /some/path
22/10/31 14:03:23 access: 429 POST /some/path
22/10/31 14:03:24 access: 429 POST /some/path
22/10/31 14:03:25 access: 429 POST /some/path
22/10/31 14:03:26 access: 429 POST /some/path
22/10/31 14:03:27 access: 429 POST /some/path
22/10/31 14:03:28 access: 429 POST /some/path
22/10/31 14:03:29 access: 429 POST /some/path
22/10/31 14:03:30 access: 429 POST /some/path
22/10/31 14:03:32 access: 200 POST /some/path
22/10/31 14:03:33 access: 429 POST /some/path

从日志中可以看到,在最初的2次请求之后,30s后第三次请求成功。这意味着,在 30 秒的正常运行时间内,有 3 个请求成功,而实际上应该只有 2 个。在 30 秒后(总共 60 秒),第四个成功的请求再次发生。

如果我将突发设置为 1,那么最初只有 1 个请求成功,每隔 30 秒就会有一个请求成功。

所以我不确定应该如何配置限制器来实现我想要的(每分钟简单的 n 个请求)。

我做错了什么?这甚至可以使用内置限制器来实现,还是我需要一个不同的库来完成此任务?

最佳答案

Limiter实现了 token 桶算法,本质上是按照规定的时间间隔喂 token 。

您在评论中提到了滑动窗口:我不相信用于速率限制的滑动窗口的“标准”实现将与您所追求的行为完全匹配。 https://konghq.com/blog/how-to-design-a-scalable-rate-limiting-algorithm下描述的方法表示应使用固定窗口的加权,并且我已经看到这种类型的方法已实现。也就是说,这仍然是一个不错的方法 - 像 https://github.com/Narasimha1997/ratelimiter 这样的库。可以为您处理这个问题。

您所描述的行为似乎更符合链接文章中所描述的“滑动日志”,您可以考虑实现该行为,尽管它描述了一些注意事项。

关于go - 使用 golang.org/x/time/rate 每分钟允许 N 个请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74264014/

相关文章:

cocoa - RestKit 支持带宽限制吗?

rate-limiting - Google Books API 限速信息?

go - 使用 Golang 从 Google 的数据存储中获取 ID

python - 从 Django webapp 安全地执行 Go 脚本

node.js - 速率限制功能在 Nestjs 应用程序中不起作用

go - 带 gorilla 复用器的速率限制器

logging - golang 1.8 : Embedded database for logging

go - 将额外数据写入 io.Writer

reflection - 为什么可以使用反射在 slice 中设置值?

amazon-web-services - 速率限制请求和 Amazon SQS