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;
}
}
如果我直接访问/文件(删除内部文件),则使用limit_conn 20规则,这是正常的。
但如果我在php脚本中使用X-Accel-Redirect来/文件,则使用limit_conn 30规则。即使我从php位置块中删除该行,也会使用来自服务器块的limit_conn 10规则,这很奇怪。最后,如果我从服务器块中删除limit_conn 10,则使用limit_conn 20规则,这是我最初期待的。
我在nginx版本1.6.2上进行了测试。
limit_conn只是一个例子,几个指令的行为都是这样的。任何想法?
答案 0 :(得分:0)
这就是limit_conn和limit_req模块的工作原理。这些模块处理用户和服务器之间的连接,并且由于内部重定向不会打开任何新的此类连接,因此Nginx仅在每个请求中检查一次限制,并且不认为有必要再次检查它们。
在您的示例中,用户的请求首先匹配第二个位置,这会触发第一次调用limit_conn处理程序。这就是使用limit_conn 30规则的原因。处理程序将在内部重定向后第二次调用,但它几乎会立即结束其工作而不检查任何内容(return NGX_DECLINED)。
如果您在第二个位置注释limit_conn 30规则,则limit_conn 10规则将从服务器上下文继承,这对于Nginx来说是完全正常的行为。在这种情况下,首先会为main请求调用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的问题。