我们正试图在Django NGINX服务器上实现请求速率限制。我阅读了一些关于如何做到这一点的文章,比如https://docs.nginx.com/nginx/admin-guide/security-controls/controlling-access-proxied-http/。
我可以看到,可以对IP地址和特定的“位置”(即API端点)设置特定的速率限制。但是,是否也可以将一些IP地址组合在一起并应用累加速率限制。
例如,我们有一个有5个IP地址的合作伙伴,我们希望在特定的API (/user/)上应用10个rps的速率限制,但是这10个rps是对所有5个IP地址的累积限制,而不是对每个IP地址的10个rps。如果可能的话,我在NGINX的官方文档或谷歌的任何地方都找不到。
为了更清晰起见,让我们考虑以下示例
123.123.123.123
- /users
- 10 rps
123.123.123.123
- /products
- 15 rps
45.45.45.45
,65.65.65.65
- /users
- 20 rps
45.45.45.45
,65.65.65.65
- /products
- 30 rps
因此,来自IP 123.123.123.123
对123.123.123.123
端点的API请求应该限制在10 rps
上,来自同一个IP的/products
端点应该有15 rps
的限制。
来自/users
端点的45.45.45.45
和65.65.65.65
组合的API请求应该仅限于20 rps
。同样,对于来自这两个IP的/products
端点,应该限制在30 rps
上。
不管调用哪个API端点,任何其他IP都有一个5 rps的默认速率限制。
希望这能消除任何混乱!谢谢!
发布于 2022-06-02 12:23:35
你的情况很复杂。例如,如果要求对由5个IP地址组成的组应用固定的10 rps速率,而对其他每一个IP应用相同的10 rps速率,则可以使用单个limit_req
区域执行此操作:
limit_req_zone $users_key zone=users:10m rate=10r/s;
geo $users_key {
<ip1> unique_customer_id;
<ip2> unique_customer_id;
<ip3> unique_customer_id;
<ip4> unique_customer_id;
<ip5> unique_customer_id;
default $binary_remote_addr;
}
server {
...
location /users/ {
limit_req zone=users;
... proxy request to the backend
}
}
该unique_customer_id
可以是任何不等于任何可能的$binary_remote_addr
值的字符串(这是一个4或16个字节长的二进制填充字符串,因此使用像1
这样简单的字符串就足够了;不要使用长id字符串来最小化共享区域内存占用)。
但是,由于您的需求更加复杂,包括针对不同用户的不同费率,我们需要声明许多不同的区域来实现您想要的结果。该解决方案基于这样一个事实,即一个空区域键不会被计算为使用单个limit_req
规则限制请求。
以下是可能的解决办法。
# zones definitions
limit_req_zone $unknown_customer zone=users_5:10m rate=5r/s;
limit_req_zone $customer_limited_group_1 zone=users_10:1m rate=10r/s;
limit_req_zone $customer_limited_group_2 zone=users_20:1m rate=20r/s;
limit_req_zone $unknown_customer zone=products_5:10m rate=5r/s;
limit_req_zone $customer_limited_group_1 zone=products_15:1m rate=15r/s;
limit_req_zone $customer_limited_group_2 zone=products_30:1m rate=30r/s;
# calculating keys
map $remote_addr $unknown_customer {
123.123.123.123 '';
45.45.45.45 '';
65.65.65.65 '';
# exclude any other IP for customers with different rates here, e.g.
# 124.124.124.124 '';
# 85.85.85.85 '';
default $binary_remote_addr;
}
map $remote_addr $customer_limited_group_1 {
123.123.123.123 1;
# here you can add another customers limited to 10/15 rps with another id, e.g.
# 124.124.124.124 2;
# the default value will be an empty string
}
map $remote_addr $customer_limited_group_2 {
# this will be a key for a different zone;
# value '1' does not interfere with the '1' from the previous map block in any way
45.45.45.45 1;
65.65.65.65 1;
# another customers limited to 20/30 rps can be added here with different ids, e.g.
# 85.85.85.85 2;
}
server {
...
location /users/ {
limit_req zone=users_5;
limit_req zone=users_10;
limit_req zone=users_20;
... proxy request to the backend
}
location /products/ {
limit_req zone=products_5;
limit_req zone=products_15;
limit_req zone=products_30;
... proxy request to the backend
}
}
https://stackoverflow.com/questions/72472008
复制相似问题