Nginx auth_request 油门不被尊重
Nginx auth_request throttle not respected
我有一个类似下面的 nginx 配置(省略了一些细节):
http {
map $request_uri $guid {
default "unknown";
~^/out/v\d+/(?P<id>.+?)/.+$ $id;
}
map $http_x_forwarded_for $last_client_ip {
default $http_x_forwarded_for;
~,\s*(?P<last_ip>[\.\d]+?)\s*$ $last_ip;
}
limit_req_zone $guid zone=content:20m rate=500r/s;
limit_req_zone $guid zone=auth:20m rate=100r/s;
server {
location /out/ {
auth_request /auth;
set $request_type "unknown";
proxy_pass $upstream_server;
proxy_cache content_cache;
set $cache_key "${request_path}";
proxy_cache_key $cache_key;
proxy_cache_valid 200 301 302 10s;
#Throttling
limit_req zone=content burst=50 nodelay;
limit_req_status 429;
}
location /auth {
internal;
set $auth_type 1;
proxy_pass_request_body off;
proxy_pass $upstream_server/auth?id=$guid&requestor=$last_client_ip;
proxy_cache auth_cache;
set $auth_cache_key "${guid}|${last_client_ip}";
proxy_cache_key $auth_cache_key;
proxy_cache_valid 200 301 302 5m;
proxy_cache_valid 401 403 404 5m;
#Throttling
limit_req zone=auth burst=50 nodelay;
limit_req_status 429;
}
}
}
/out/
的请求限制正如我预期的那样工作 - 超过 500r/s 的请求会受到限制。但是,我似乎无法启动 /auth
节流。
我猜这可能是由于 auth_request
和 limit_req
之间的某些相互作用,或者可能是因为 /auth
请求是子请求。如果有任何帮助或解释,我将不胜感激!
我怀疑它与您用作 key 的变量有关:$guid。这不是一个 nginx 变量,遗憾的是你的代码片段没有显示你是如何定义它的。但是您将它传递给代理的方式让我怀疑对 /auth 的每个请求都有不同的 $guid。然后你永远不会 运行 进入限制,因为 nginx 计算每个键的请求,请参见此处:https://www.nginx.com/blog/rate-limiting-nginx/
因此,如果根本没有为 /out/ 设置 $guid,则所有请求都将计入限制。没问题。但是如果每次请求/auth确实不一样,那就不行了。
我从 Nginx 邮件列表收到了对此行为的解释:
The limit_req directive doesn't try to limit requests already limited,
as well as subrequests within these requests. You should configure all
limits you want to apply to a request in one place.
(见https://forum.nginx.org/read.php?2,280554,280558#msg-280558)
我有一个类似下面的 nginx 配置(省略了一些细节):
http {
map $request_uri $guid {
default "unknown";
~^/out/v\d+/(?P<id>.+?)/.+$ $id;
}
map $http_x_forwarded_for $last_client_ip {
default $http_x_forwarded_for;
~,\s*(?P<last_ip>[\.\d]+?)\s*$ $last_ip;
}
limit_req_zone $guid zone=content:20m rate=500r/s;
limit_req_zone $guid zone=auth:20m rate=100r/s;
server {
location /out/ {
auth_request /auth;
set $request_type "unknown";
proxy_pass $upstream_server;
proxy_cache content_cache;
set $cache_key "${request_path}";
proxy_cache_key $cache_key;
proxy_cache_valid 200 301 302 10s;
#Throttling
limit_req zone=content burst=50 nodelay;
limit_req_status 429;
}
location /auth {
internal;
set $auth_type 1;
proxy_pass_request_body off;
proxy_pass $upstream_server/auth?id=$guid&requestor=$last_client_ip;
proxy_cache auth_cache;
set $auth_cache_key "${guid}|${last_client_ip}";
proxy_cache_key $auth_cache_key;
proxy_cache_valid 200 301 302 5m;
proxy_cache_valid 401 403 404 5m;
#Throttling
limit_req zone=auth burst=50 nodelay;
limit_req_status 429;
}
}
}
/out/
的请求限制正如我预期的那样工作 - 超过 500r/s 的请求会受到限制。但是,我似乎无法启动 /auth
节流。
我猜这可能是由于 auth_request
和 limit_req
之间的某些相互作用,或者可能是因为 /auth
请求是子请求。如果有任何帮助或解释,我将不胜感激!
我怀疑它与您用作 key 的变量有关:$guid。这不是一个 nginx 变量,遗憾的是你的代码片段没有显示你是如何定义它的。但是您将它传递给代理的方式让我怀疑对 /auth 的每个请求都有不同的 $guid。然后你永远不会 运行 进入限制,因为 nginx 计算每个键的请求,请参见此处:https://www.nginx.com/blog/rate-limiting-nginx/
因此,如果根本没有为 /out/ 设置 $guid,则所有请求都将计入限制。没问题。但是如果每次请求/auth确实不一样,那就不行了。
我从 Nginx 邮件列表收到了对此行为的解释:
The limit_req directive doesn't try to limit requests already limited, as well as subrequests within these requests. You should configure all limits you want to apply to a request in one place.
(见https://forum.nginx.org/read.php?2,280554,280558#msg-280558)