【问题标题】:nginx limit_req does not worknginx limit_req 不起作用
【发布时间】:2015-04-09 10:53:53
【问题描述】:

我正在尝试使用 nginx (v1.6.2) 实现一个简单的速率限制系统

sites-available/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 端点。

【问题讨论】:

    标签: nginx webserver rewrite rate


    【解决方案1】:

    问题是 nginx 进程请求在几个 phasesrewrite 阶段先于 preaccess 一个(这是应用 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;
        }
    }
    

    【讨论】:

    • 哇,这真的是唯一可行的方法吗?我的意思是这真的 hackish .. :(
    • 什么 SOME_NONEXISTENT_FILE?
    • @CuriousDeveloper 任何在 /var/www/vhosts/mysite.com 中不存在的文件名
    • 感谢@AlexeyTen。有没有办法在/api/index.php 文件上添加连接限制。我的服务器具有所有 API 的上述路径,我想在此文件上添加连接限制?我已经尝试了很多事情,并花了几个小时来确定正确的事情。有什么解决办法吗?
    • @AlexeyTen。你可以在这里查看我的问题unix.stackexchange.com/questions/578781/… 吗?也许你可以回答我的问题。
    猜你喜欢
    • 2014-12-16
    • 2019-05-31
    • 2017-01-02
    • 2011-12-23
    • 1970-01-01
    • 2018-01-14
    • 2015-05-02
    • 2017-11-23
    • 1970-01-01
    相关资源
    最近更新 更多