nginx x-accel block conflict


nginx x-accel block conflict

X-Accel-Redirect似乎不遵守nginx块配置规则和先例。请考虑以下示例:

server {
   ...
   limit_conn limitedIP 10;
   location ^~ /files/ {
      internal
      alias /var/www/files/;
      limit_conn limitedIP 20;
   }
   location ~ '.php$ {
      ...
      limit_conn limitedIP 30;
   }
}

如果我直接访问/files(当然在删除内部文件时),则使用 limit_conn 20 规则,这是正常的。

但是如果我在 php 脚本中使用 X-Accel-重定向到/files,则使用 limit_conn 30 规则。 即使我从 php 位置块中删除该行,也会使用服务器块中的 limit_conn 10 规则,这很奇怪。 最后,如果我从服务器块中删除limit_conn 10 limit_conn则使用我最初期待的 20 规则。

我在nginx版本1.6.2上对此进行了测试。

limit_conn只是一个例子,有几个指令的行为是这样的。 有什么想法吗?

这就是limit_conn和limit_req模块的工作方式。这些模块处理用户和服务器之间的连接,并且由于内部重定向不会打开任何新的此类连接,因此Nginx仅检查每个请求一次限制,并且认为没有必要再次检查它们。

在您的示例中,用户的请求首先与第二个位置匹配,这会触发首次调用limit_conn处理程序。这就是使用 limit_conn 30 规则的原因。处理程序将在内部重定向后第二次调用,但它几乎会立即结束其工作而不检查任何内容(返回 NGX_DECLINED)。

如果在第二个位置注释 limit_conn 30 规则,则 limit_conn 10 规则将从服务器上下文继承,这对于 Nginx 来说是完全正常的行为。在这种情况下,同样,将首先为主请求调用limit_conn处理程序,下一次调用(在内部重定向之后)将不执行任何操作。

最后,当您注释除 limit_conn 20 规则之外的所有limit_conn行时,将在内部重定向后首先调用 limit_conn 处理程序,因此最终将使用此规则。

更新:

由于在建立新连接时会检查limit_conn规则,因此打开新连接将解决您的问题。从概念上讲,配置如下所示:

limit_conn_zone $binary_remote_addr zone=limitedIP:10m;
server {
    # You can use any random unused non-system port
    listen 127.0.0.1:8889;
    server_name internal.server;
    set_real_ip_from  127.0.0.1/32;
    real_ip_header    X-Forwarded-For;
    location ^~ /files/ {
        limit_conn limitedIP 20;
        alias /var/www/files/;
    }
}
server {
    ...
    location ^~ /files/ {
        internal;
        proxy_set_header Host "internal.server";
        proxy_set_header X-Forwarded-For $remote_addr;
        # Make sure you specify the same port as above
        proxy_pass http://127.0.0.1:8889;
    }
    location ~ '.php$ {
        ...
        limit_conn limitedIP 30;
    }
}

但是,此方法将导致性能明显下降,尤其是在文件很大的情况下。因此,我不建议使用此解决方法。

不幸的是,我无法想象任何其他方法可以仅使用Nginx解决问题。