nginx x-accel块冲突

时间:2014-12-25 20:36:02

标签: php nginx x-accel-redirect

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只是一个例子,几个指令的行为都是这样的。任何想法?

1 个答案:

答案 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的问题。