Nginx 限速与并发限制

没有限流的服务很容易被刷爆:一个脚本就能打满带宽或连接数。Nginx 的 limit_req 限制请求速率(令牌桶思想)、limit_conn 限制并发连接、limit_rate 限制传输速度,三道闸门各管一段。

请求速率限制 limit_req

limit_req 令牌桶 先用 limit_req_zone 定义共享区域与速率,再在 location 里引用:

http {
    # 按客户端 IP 限速 1 请求/秒,zone 存 10m 共享状态(约可记录 16 万个 IP)
    limit_req_zone $binary_remote_addr zone=req_one:10m rate=1r/s;

    server {
        location /api/ {
            limit_req zone=req_one burst=5 nodelay;   # 突发容忍 5 个
            proxy_pass http://backend;
        }
    }
}

令牌桶语义:rate=1r/s 表示匀速每秒补充 1 个令牌;burst=5 允许瞬间多放行 5 个积压请求(相当于桶容量);加 nodelay 后超出的突发请求立即处理而不排队,真正超过 rate+burst 的请求直接拒绝:

# 快速连发 10 个请求(速率补充需要时间,典型结果如下)
for i in $(seq 1 10); do curl -s -o /dev/null -w "%{http_code}\n" http://example.com/api/; done
# 输出:前 6 个 200,其余 503

被拒绝的默认返回 503,可改成 429(Too Many Requests)或跳自定义页:

limit_req_status 429;
# 自定义提示页:error_page 503 /too-fast.html;

并发连接限制 limit_conn

防止同一 IP 把连接数占满,限制其同时建立的连接数:

http {
    limit_conn_zone $binary_remote_addr zone=conn_ip:10m;

    server {
        limit_conn conn_ip 10;      # 每个 IP 最多 10 个并发连接
        limit_conn_status 503;      # 超限返回 503
    }
}

限速上传与下载

上传接口按业务需要调大请求体上限(默认仅 1m);下载场景用 limit_rate 限制单连接速率:

server {
    client_max_body_size 20m;       # 允许上传最大 20MB

    location /download/ {
        limit_rate 500k;            # 单连接下载限速 500KB/s
        root /var/www/files;
    }
}
curl -o /dev/null -s -w '平均速度:%{speed_download} B/s\n' http://example.com/download/big.zip

补充

  • 想按国家/地区限流:可编译 --with-http_geoip_module(旧版 GeoIP 数据库,社区多在维护)或改用第三方 GeoIP2 方案,把区域解析成变量后再套用上面相同的 zone。
  • 以上限制均针对单 IP / 单连接,分布式攻击需在防火墙、云盾等更上层联合治理。

小结

限流三板斧:limit_req_zone + limit_req 管每秒请求数(rate/burst/nodelay 三参数要一起理解),limit_conn 管并发连接数,limit_rate 管单连接速度;超限提示用 limit_req_status 或 error_page 处理得友好一些。

笔记加载中…