我想要的:
每分钟允许 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 个请求)。
我做错了什么?这甚至可以通过使用内置的限制器来实现吗?或者我需要一个不同的库来完成这个任务吗?
1条答案
按热度按时间2vuwiymt1#
Limiter
实现令牌桶算法,其本质上以规定的间隔馈送令牌。您在评论中提到了滑动窗口:我不相信一个“标准”的滑动窗口速率限制的实现会完全符合你所追求的行为。https://konghq.com/blog/how-to-design-a-scalable-rate-limiting-algorithm下描述的方法表明应该使用固定窗口的加权,我已经看到了这种类型的方法的实现。也就是说,它仍然是一个不错的方法-像https://github.com/Narasimha1997/ratelimiter这样的库可以为你处理这个问题。
您所描述的行为似乎更符合链接文章中所描述的“滑动日志”,您可以考虑实现它,尽管它描述了一些注意事项。