我想根据一天中的时间限制对我服务的请求
它应该是夜间4 r / s(21:00 - 06:59)和白天1 r / s(07:00-20:59)。
我可以有2个不同的req_limit_zone
喜欢
limit_req_zone $server_name zone=day:1m rate=1r/s;
limit_req_zone $server_name zone=night:1m rate=4r/s;
但我如何根据一天中的时间在limit_req
中区别?
nginx背后的服务是另一个具有上述限制的服务的API包装器。我的服务是用Flask-RESTful
编写的,由uWSGI
运行,只有几个进程,所以实现限制逻辑并在进程之间用redis
之类的方法同步它会非常痛苦。
这样可以配置nginx吗? 如果不是,是否有任何常见的解决方法?其他服务如何解决这个问题呢? 更具体地说,它应该是一个泄漏的存储桶,因此客户端只是等待答案而没有任何错误,如HTTP 429 Too Many Requests。
答案 0 :(得分:0)
关键是绑定limit_req_zone
和map
。
在文档中有关于它们的两个相关注释。 map:
默认值
如果源值与任何指定的变量都不匹配,则设置结果值。如果未指定
default
,则默认结果值为空字符串。
limit_req_zone key zone = name:size rate = rate;
设置共享内存区域的参数,该区域将保留各种键的状态。特别是,状态存储当前的过多请求数。
key
可以包含文本,变量及其组合。 没有计算空键值的请求。
如果它应该工作,那么只需使用 day 和 night limit_req_zone
并将$server_name
作为键并且如果它不应该是空字符串。 map
将返回$server_name
或空字符串,具体取决于一天中的时间。
map $date_gmt $day {
# 07:00-20:59 GMT
~(0[7-9]|1[0-9]|20):[0-5][0-9]:[0-5][0-9] $server_name;
}
map $date_gmt $night {
# 21:00-06:59 GMT
~(2[1-4]|0[0-6]):[0-5][0-9]:[0-5][0-9] $server_name;
}
limit_req_zone $day zone=day_zone:1m rate=1r/s;
limit_req_zone $night zone=night_zone:1m rate=4r/s;
...
limit_req zone=day_zone burst=100;
limit_req zone=night_zone burst=100;
req_limit
首次尝试我尝试在limit_req
中使用映射变量,但是nginx并不理解这种语法。更进一步,乍一看nginx -s reload
没有任何问题,但事实上没有任何重新加载,只有service nginx restart
显示错误(nginx版本:1.12.2)。所以我想展示一个应该怎么做:
limit_req_zone $server_name zone=day:1m rate=1r/s;
limit_req_zone $server_name zone=night:1m rate=4r/s;
map $date_gmt $time_of_day {
~(0[7-9]|1[0-9]|20):[0-5][0-9]:[0-5][0-9] day;
~(2[1-4]|0[0-6]):[0-5][0-9]:[0-5][0-9] night;
}
...
limit_req zone=$time_of_day burst=100;
由于每次请求都需要双倍检查,因此它不是最佳解决方案。有两个单独的nginx配置选项,并用cron之类的东西切换它们。这将是丑陋和错误,因为你应该记得编辑两个配置,但它会更快;我认为这个选项应该作为最后的手段。如果能够进行水平扩展,则可以更好地对多个服务器进行负载均衡。 在我看来,这不是什么大不了的事:服务每小时只能获得8k个请求(2.2 r / s)。