一. 前言

Nginx 内置了强大的限流模块,可以轻松实现基于 IP、用户、API Key 的请求频率限制。


Nginx 原生限流:使用 limit_req 模块

Nginx 提供了 ngx_http_limit_req_module 模块,可以实现 漏桶算法(Leaky Bucket) 的限流机制。


1. 基本配置:按 IP 限流(常用)

http {
    # 定义一个限流区,名为 'per_ip'
    # zone=名称:大小(1MB ≈ 16000 个并发连接)
    # rate=每秒允许的请求数(r/s)
    limit_req_zone $binary_remote_addr zone=per_ip:10m rate=10r/s;

    server {
        listen 80;
        server_name api.yourdomain.com;

        location /v1/ {
            # 应用限流规则
            # burst=突发请求数(超出 rate 的请求可排队)
            # nodelay=不延迟处理(立即处理 burst 内请求)
            limit_req zone=per_ip burst=20 nodelay;

            proxy_pass http://qwen-api:8000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}

✅ 效果说明:

  • 每个 IP 最多 10 请求/秒
  • 允许突发 20 个请求(burst=20)
  • 突发请求不排队,立即处理(nodelay)
  • 超出限制的请求返回 503 Service Temporarily Unavailable

🔧 2. 按 API Key 限流(推荐用于 API 服务)

http {
    # 使用 $http_apikey 变量(来自请求头)
    limit_req_zone $http_apikey zone=per_key:10m rate=100r/m;  # 100次/分钟

    server {
        listen 80;
        server_name api.yourdomain.com;

        location /v1/ {
            # 验证 API Key 有效性(可结合 map)
            if ($http_apikey = "") {
                return 401 "Missing API Key";
            }

            # 应用按 key 限流
            limit_req zone=per_key burst=20 nodelay;

            proxy_pass http://qwen-api:8000;
            proxy_set_header Host $host;
        }
    }
}

✅ 效果说明:

  • 每个 API Key 最多 100 请求/分钟
  • 支持突发 20 次请求
  • 适合多租户 API 服务

3. 组合限流:IP + Key 双重保护

http {
    limit_req_zone $binary_remote_addr zone=per_ip:10m rate=5r/s;
    limit_req_zone $http_apikey zone=per_key:10m rate=100r/m;

    server {
        location /v1/ {
            # 先按 IP 限流
            limit_req zone=per_ip burst=10 nodelay;
            # 再按 Key 限流
            limit_req zone=per_key burst=20 nodelay;

            proxy_pass http://qwen-api:8000;
        }
    }
}

⚠️ 注意:多个 limit_req 是 “与”关系,必须同时满足。


限流参数详解

参数说明
zone=name:size共享内存区名称和大小
rate=10r/s速率:每秒 10 请求
rate=100r/m速率:每分钟 100 请求
burst=20突发队列大小(允许超出 rate 的请求数)
nodelay不延迟处理突发请求(立即处理)
delay=自定义延迟(高级用法)

超出限制的响应

默认返回 503,你可以自定义错误页:

location /v1/ {
    limit_req zone=per_key burst=20 nodelay;
    
    # 自定义限流错误
    error_page 503 = @rate_limit_exceeded;
}

location @rate_limit_exceeded {
    internal;
    add_header Content-Type "application/json";
    return 429 '{"error": "Too Many Requests", "message": "Request limit exceeded"}';
}

✅ 推荐使用 429 Too Many Requests 状态码


验证限流是否生效

# 使用 ab(Apache Bench)测试
ab -n 150 -c 20 http://api.yourdomain.com/v1/chat/completions

# 或使用 curl 循环
for i in {1..120}; do
  curl -H "apikey: your-key" http://localhost/v1/models
done

查看 Nginx 错误日志:

tail -f /var/log/nginx/error.log
# 会看到类似:
# [error] 1234#0: *5 limit_req limit exceeded

优点 vs 缺点

优点缺点
✅ 原生支持,无需额外依赖❌ 无法持久化统计(重启清零)
✅ 性能极高,几乎无开销❌ 不支持复杂的配额管理(如按天限额)
✅ 配置简单,易于维护❌ 集群环境下无法共享状态(需配合 Redis)

什么时候用 Nginx 原生限流?

场景推荐方案
单机部署、简单限流✅ Nginx limit_req
集群部署、全局限流✅ Redis + Lua
需要配额管理、计费✅ 独立鉴权服务 + DB

✅ 总结

是的,Nginx 可以直接设置限流,使用 limit_req_zone 和 limit_req 指令即可实现高效、低开销的请求频率控制。

推荐配置(API 服务):

limit_req_zone $http_apikey zone=api_key:10m rate=100r/m;

location /v1/ {
    if ($http_apikey = "") { return 401; }
    limit_req zone=api_key burst=20 nodelay;
    error_page 503 = 429 '{"error":"Too Many Requests"}';
    proxy_pass http://backend;
}

如果你需要 集群级限流 或 更复杂的策略(如按用户等级限流),再考虑 Redis 或外部服务。对于大多数场景,Nginx 原生限流已经足够强大!

以上就是关于【Nginx】限流设置的基本应用介绍,希望对你有所帮助!

更多推荐