如何防止 nginx 节流与维护模式冲突?

如何防止 nginx 节流与维护模式冲突?

我们使用HttpLimitReq模块nginx mondule 用于速率限制,并且发现它与我们的“维护模式“因为两个组件都使用http 状态代码 503

当节流被激活时(通过限制请求数指令),nginx 通常会提供 503,但不幸的是我们的维护模式位置被使用了,这导致我们的 Amazon S3 托管维护页面出现 302 错误。对于受限制的请求,302 不是一个好结果

我想知道其他人如何处理这个问题?例如,我是否应该为我们的维护页面使用不同的状态代码,但如果是的话,该怎么办?

理想情况下,对于受限制的请求,我不希望提供任何页面,只希望提供 503 响应标头 - 它需要尽可能轻量,因为重点是阻止服务器不堪重负。


作为参考,这是我们用于“维护模式”的 nginx 配置:

server {
    ...

    # Redirect processing of 503 error pages into a named location:
    error_page 503 @maintenance;

    # "Maintenance Mode" is off by default - Use a nginx variable to track state.
    set $maintenance off;

    # Switch on "Maintenance Mode" if a certain file exists.
    if (-f /var/www/mysite/shared/maintenanceON) {
        set $maintenance on;
    }

    if ($maintenance = on) {
        return 503; # 503 - Service unavailable
    }

    location @maintenance {
        # Redirect the request to our maintenance page in Amazon S3.
        rewrite ^(.*)$ http://mysite.s3-website-us-east-1.amazonaws.com/ break;
    }
    ...
    # Process the php files - pass to php-fpm.
    location ~ \.php {
        # Limit aggressive bots and crawlers to 30 requests per minute.
        limit_req zone=bots;

        fastcgi_pass 127.0.0.1:$fastcgi_port;
    }
    ...

答案1

对于“维护模式”,请使用 503 以外的状态代码。

我们可以清楚地看到,当您使用“维护模式”时,用户实际上不会收到 503 状态代码,因此在配置中内部使用该状态代码没有任何好处。编写另一个代码(593?)并使用它。


或者更好的是,跳过额外的部分,当维护文件存在时直接location发送。rewrite

    if (-f /var/www/mysite/shared/maintenanceON) {
        rewrite ^(.*)$ http://mysite.s3-website-us-east-1.amazonaws.com/ redirect;
    }

答案2

从 nginx 1.3.15 开始,有一个“limit_req_status“指令允许您指定节流阀将返回的 http 响应代码。

# Define a limit request zone called "bots" that will track requests by IP.
limit_req_zone $binary_remote_addr zone=bots:20m rate=15r/s;

# 429 = Too Many Requests
limit_req_status 429;

http 状态 429 表示“ Too Many Requests” - 此代码已被接受RFC 6585 其他 HTTP 状态代码. 例如,它用于Twitter REST API 速率限制器

迈克尔的回答也能工作,因为在我的配置中 503 仅由 nginx 内部使用)。

相关内容