【问题标题】:nginx set remaining count for limit_req in X-RateLimit-Remaining headernginx 在 X-RateLimit-Remaining 标头中设置 limit_req 的剩余计数
【发布时间】:2015-12-11 07:40:59
【问题描述】:

我在谷歌上搜索了几个小时后找不到任何东西,其实有点惊讶,但问题如下:

我希望 nginx 充当我的 API 的节流阀。

我的配置文件包含一个被广泛引用的 limit_req_zone 示例:

limit_req_zone $binary_remote_addr zone=limit:2m rate=10r/m;

连同我的 location 指令,其中包含预期的 limit_req zone=limit nodelay;

我希望 nginx 将标头附加到 X-RateLimit-RemainingX-RateLimit-Reset 属性的响应消息中。基本上让 nginx 使用rate=10r/m 的活动计数来填充X-RateLimit-Remaining 和相同rate=10r/m 值的时间范围来填充X-RateLimit-Reset,在刷新前还剩多少秒。

http {
    limit_req_zone $binary_remote_addr zone=login:10m rate=2r/s;
    limit_req_status 429;
    limit_conn_status 429;

    server {
        listen       80;
        server_name  [removed];

        location / {
            limit_req zone=limit nodelay;

            proxy_pass http://reverse-proxy-example;
            add_header  X-RateLimit-Remaining [nginx variable?];
            add_header  X-RateLimit-Reset [nginx variable?]
        }
}

想法?可能的?希望避免点击应用程序来获取这些数字。

【问题讨论】:

  • FWIW 我 grepped NGinx 源代码,找不到任何对 Remaining 或 Reset 值的引用。
  • 我知道一些框架已经内置了速率限制,但想想看,我们必须将请求传递给应用程序,加载/执行代码,连接到 redis 只是为了跟踪速率限制参数。在服务器级别处理它会好得多,尤其是使用 NGinx 更好的内置内存管理。

标签: nginx server devops


【解决方案1】:

我会说这对于 nginx 的上游版本是不可能的。

您可以通过http://nginx.org/r/limit_req 找到limit_req 指令的文档,该指令重定向到http://nginx.org/docs/http/ngx_http_limit_req_module.html#limit_req,这最终表明该模块中没有任何已知变量。

查看http://ngx.su/src/http/modules/ngx_http_limit_req_module.c证实了猜想。

另一种选择是查看 http://nginx.org/docs/varindex.html,它列出了所有变量 - 查找 limit 只会让您找到 $limit_rate,这是一个不相关的变量。


附:考虑limit_req 是通过 leaky bucket 方法完成的。

在不深入细节或编造东西的情况下(维基百科的文章很大!),我猜想以一致且可操作的方式向最终用户呈现这些信息可能并非完全微不足道。

【讨论】:

    【解决方案2】:

    就像@cnst的回答一样,没有一个合适的变量来保存你想要的值,如果你真的想要这个消息,你可以实现一个lua函数来保存这个消息。 nginx 配置是这样的:

    http {
        limit_req_zone $binary_remote_addr zone=login:10m rate=2r/s;
        limit_req_status 429;
        limit_conn_status 429;
    
        server {
            listen       80;
            server_name  [removed];
            set $x-ratelimit-ramaining 0;
            set $x-ratelimit-reset 0;
            access_by_lua_file your_file_name.lua;
    
            location / {
                limit_req zone=limit nodelay;
    
                proxy_pass http://reverse-proxy-example;
                add_header  X-RateLimit-Remaining $x-rate-limit-remaining;
                add_header  X-RateLimit-Reset $x-ratelimit-reset;
            }
    }
    

    因此,每个请求都会触发 lua 脚本,您可以在 lua 函数中更新变量 $x-rate-limit-remaining $x-ratelimit-reset

    【讨论】:

      【解决方案3】:

      来自PacketPackngo 有一个功能可能非常适合您需要做的事情。

      packngo 的示例:

      func (r *Response) populateRate() {
          // parse the rate limit headers and populate Response.Rate
          if limit := r.Header.Get(headerRateLimit); limit != "" {
              r.Rate.RequestLimit, _ = strconv.Atoi(limit)
          }
          if remaining := r.Header.Get(headerRateRemaining); remaining != "" {
              r.Rate.RequestsRemaining, _ = strconv.Atoi(remaining)
          }
          if reset := r.Header.Get(headerRateReset); reset != "" {
              if v, _ := strconv.ParseInt(reset, 10, 64); v != 0 {
                  r.Rate.Reset = Timestamp{time.Unix(v, 0)}
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2020-06-28
        • 1970-01-01
        • 2019-05-31
        • 2020-07-20
        • 1970-01-01
        • 2021-11-15
        • 1970-01-01
        • 1970-01-01
        • 2014-06-11
        相关资源
        最近更新 更多