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解决问题。