【问题标题】:Nginx auth_request throttle not respectedNginx auth_request 限制不受尊重
【发布时间】:2018-07-19 04:55:18
【问题描述】:

我有一个如下的 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_requestlimit_req 之间的一些相互作用,或者可能是因为/auth 请求是子请求。我将不胜感激任何帮助或解释!

【问题讨论】:

    标签: nginx nginx-reverse-proxy throttling


    【解决方案1】:

    我怀疑这与您用作 key 的变量有关:$guid。这不是一个 nginx 变量,遗憾的是你的 sn-p 没有显示你是如何定义它的。但是你将它传递给你的代理的方式让我怀疑对 /auth 的每个请求都有不同的 $guid。然后您将永远不会遇到限制,因为 nginx 会计算每个键的请求数,请参见此处:https://www.nginx.com/blog/rate-limiting-nginx/

    因此,如果根本没有为 /out/ 设置 $guid,那么所有请求都将计入限制。没问题。但如果对 /auth 的每个请求确实不同,那么它就行不通了。

    【讨论】:

    • $guid 应唯一标识特定资源,并且对该资源的所有请求都应具有相同的$guid。该变量似乎设置正确,因为 auth 缓存也使用它作为键,并且缓存的行为符合预期。
    • 我更新了 sn-p 以显示 $guid 的来源。
    • @JaredStewart,对于匹配此正则表达式 ~^/out/v\d+/(?P&lt;id&gt;.+?)/.+$ 的请求,$guid 确实指定了请求的资源。但是对于要求 /auth 的请求,正则表达式不匹配,并且 $guid 对于所有这些都是“未知的”。这不应该是个问题,但由于这是两者之间最明显的区别,我会尝试使用$binary_remote_addr 作为第二个limit_req_zone 的键。由于 /auth 不查询特定的资源,我认为无论如何最好由客户端限制。
    【解决方案2】:

    我从 Nginx 邮件列表中收到了对此行为的解释:

    limit_req 指令不会尝试限制已经受限的请求, 以及这些请求中的子请求。你应该配置所有 您想在一个地方对请求应用限制。

    (见https://forum.nginx.org/read.php?2,280554,280558#msg-280558

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-18
      • 2017-02-20
      • 2018-06-12
      • 2020-02-21
      • 1970-01-01
      • 2021-12-21
      • 2016-06-11
      • 2017-03-18
      相关资源
      最近更新 更多