limit_req按时间区分不同的区域

时间:2018-06-13 10:31:14

标签: nginx rate-limiting

我想根据一天中的时间限制对我服务的请求 它应该是夜间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。

1 个答案:

答案 0 :(得分:0)

答案

关键是绑定limit_req_zonemap。 在文档中有关于它们的两个相关注释。 map

  

默认

     
    如果源值与任何指定的变量都不匹配,则

设置结果值。如果未指定default,则默认结果值为空字符串

  

limit_req_zone

  

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)。