nginx - limit_req 按一天中的时间区分区域
问题描述
我想根据一天中的时间限制对我的服务的请求。
夜间 (21:00 - 06:59) 应为 4 r/s,白天 (07:00-20:59) 应为 1 r/s。
我可以有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。
解决方案
答案
关键是绑定limit_req_zone
和map
。文档中有两个关于它们的相关说明。地图:
默认值
如果源值不匹配任何指定的变体,则设置结果值。如果
default
未指定,则默认结果值为空字符串。
limit_req_zone key zone=name:size rate=rate;
为共享内存区域设置参数,该区域将保持各种键的状态。特别是,状态存储当前过多请求的数量。可以包含文本、
key
变量及其组合。不计入空键值的请求。
因此,如果它应该工作,则只需使用白天和夜晚 作为键,如果不应该使用空字符串。并将根据一天中的时间返回一个或空字符串。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)。
推荐阅读
- testng - AWS Device Farm 忽略 TestNG 优先级注释
- javascript - 如何在 Picker React-native 中获取 JSON 动态值
- sql-server - 为什么 LEN() 的输出与 DATALENGTH() 不同
- cakephp-3.0 - Cakephp 3.1 与 PHP7.2 有问题
- python - 请求内容中带有 unicode 字符的 Python JSON 解码器错误
- php - 如何使用codeigniter从数据库中检索hass或逗号分隔值?
- angular - Angular 6 - 对文本类型的所有输入的全局检查/验证
- kartik-v - Yii2 kartik-v 导出菜单
- imagemagick - Homebrew 的配方无法识别
- jquery - 每次点击更改班级