2015-02-09 29 views
0

我试图实现与nginx的(V1.6.2)一个简单的速率限制系统nginx的limit_req不起作用

网站可用/ mysite.com

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

server { 
    listen      80; 
    server_name     mysite.com; 
    root      /var/www/vhosts/mysite.com; 
    error_log     [..]; 
    access_log     [..]; 

    include      conf.d/php-fpm.conf; 

    location =/{ 
     limit_req    zone=myzone burst=3 nodelay; 
     index     index.html; 
    } 

    location/{ 
     try_files    $uri =404; 
    } 

    location ^~ /pages { 
     include     conf.d/php-fpm.conf; 
     internal; 
    } 

    location = /email { 
     rewrite ^(.*)$   /pages/email.html; 
    } 

    location = /email/subscribe { 
     limit_req    zone=myzone burst=2 nodelay; 
     rewrite ^(.*)$   /pages/email.php?action=subscribe; 
    } 

    location ~ /api { 
     limit_req    zone=myzone burst=5 nodelay; 
     rewrite ^(.*)$   /pages/api.php; 
    } 
} 

的conf。 d/PHP-fpm.conf

location ~ \.php$ { 
    if (!-f $document_root$fastcgi_script_name) { 
     return 404; 
    } 
    fastcgi_pass    unix:/var/run/php5-fpm.sock; 
    fastcgi_index    index.php; 
    fastcgi_param    SCRIPT_FILENAME $document_root$fastcgi_script_name; 
    fastcgi_split_path_info  ^(.+?\.php)(/.*)$; 
    fastcgi_param    PATH_INFO $fastcgi_path_info; 
    include      fastcgi_params; 
} 

nginx.conf: 没有什么有趣的,只有
include sites-enabled/*;

限速/工作正常。如果我对此页面提出太多请求,则会收到错误503。
问题:/email/subscribe,/api/api/test都没有速率限制,我不知道为什么。它必须与rewrite做些什么,但是问题是什么?
任何想法?我尝试了一切!

请注意:我更改了文件名和URL端点。

+0

你已经从配置中删除了太多 – 2015-02-09 17:51:10

+0

我不这么认为。除了server_name之外没有其他的东西.. – 2015-02-09 17:53:22

+0

那么,你的'/ test'位置重写为'/ test.txt',并且该文件与'location =/test'不匹配,所以它由其他位置(或者_default_位置),它显然不包含'limit_req'指令。 – 2015-02-09 18:01:34

回答

3

问题是前preaccess一个在几个phases重写该nginx的处理请求阶段进入(这是其中应用limit_req)。所以在你配置请求被重写为/pages/...之前,他们有机会受到限制。为了避免这种情况,你应该在重写之后(使用break标志)或者与try_files一起保留在同一个位置块中。

我更喜欢第一个选项,让你的配置看起来是这样的:

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

server { 
    listen      80; 
    server_name     mysite.com; 
    root      /var/www/vhosts/mysite.com; 
    error_log     [..]; 
    access_log     [..]; 

    include      conf.d/php-fpm.conf; 

    location =/{ 
     limit_req    zone=myzone burst=3 nodelay; 
     index     index.html; 
    } 

    location/{ 
     try_files    $uri =404; 
    } 

    location ^~ /pages { 
     include     conf.d/php-fpm.conf; 
     internal; 
    } 

    location = /email { 
     rewrite ^(.*)$   /pages/email.html; 
    } 

    location = /email/subscribe { 
     limit_req    zone=myzone burst=2 nodelay; 
     rewrite ^(.*)$   /pages/email.php?action=subscribe break; 
     fastcgi_pass   unix:/var/run/php5-fpm.sock; 
     fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name; 
     include     fastcgi_params; 
    } 

    location ~ /api { 
     limit_req    zone=myzone burst=5 nodelay; 
     rewrite ^(.*)$   /pages/api.php break; 
     fastcgi_pass    unix:/var/run/php5-fpm.sock; 
     fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name; 
     include     fastcgi_params; 
    } 
} 

如果使用第二个选项去,你的配置将是干净了一点,但有点哈克。我们将使用try_files阶段在limit_req阶段之后运行并且try_files将内部重定向到它的最后一个参数。

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

server { 
    listen      80; 
    server_name     mysite.com; 
    root      /var/www/vhosts/mysite.com; 
    error_log     [..]; 
    access_log     [..]; 

    include      conf.d/php-fpm.conf; 

    location =/{ 
     limit_req    zone=myzone burst=3 nodelay; 
     index     index.html; 
    } 

    location/{ 
     try_files    $uri =404; 
    } 

    location ^~ /pages { 
     include     conf.d/php-fpm.conf; 
     internal; 
    } 

    location = /email { 
     rewrite ^(.*)$   /pages/email.html; 
    } 

    location = /email/subscribe { 
     limit_req    zone=myzone burst=2 nodelay; 
     try_files SOME_NONEXISTENT_FILE /pages/email.php?action=subscribe; 
    } 

    location ~ /api { 
     limit_req    zone=myzone burst=5 nodelay; 
     try_files SOME_NONEXISTENT_FILE /pages/api.php; 
    } 
} 
+0

哇,这是真的唯一可能的方式?我的意思是这是真的* hackish .. :( – 2015-02-10 19:14:47