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

vaqhlq81  于 2022-12-07  发布在  Go
关注(0)|答案(1)|浏览(83)

我想要的:

每分钟允许 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个请求之后,第三个成功的请求在30秒后发生。这意味着,在30秒的正常运行时间内,有3个请求成功,而实际上应该只有2个。第四个成功的请求在30秒后再次发生(总共60秒)。
如果我将猝发设置为1,那么最初只有1个请求成功,每隔30秒就有一个请求成功。
所以我不确定应该如何配置限制器来达到我想要的(每分钟普通 n 个请求)。
我做错了什么?这甚至可以通过使用内置的限制器来实现吗?或者我需要一个不同的库来完成这个任务吗?

2vuwiymt

2vuwiymt1#

Limiter实现令牌桶算法,其本质上以规定的间隔馈送令牌。
您在评论中提到了滑动窗口:我不相信一个“标准”的滑动窗口速率限制的实现会完全符合你所追求的行为。https://konghq.com/blog/how-to-design-a-scalable-rate-limiting-algorithm下描述的方法表明应该使用固定窗口的加权,我已经看到了这种类型的方法的实现。也就是说,它仍然是一个不错的方法-像https://github.com/Narasimha1997/ratelimiter这样的库可以为你处理这个问题。
您所描述的行为似乎更符合链接文章中所描述的“滑动日志”,您可以考虑实现它,尽管它描述了一些注意事项。

相关问题