【Nginx】限流设置

一. 前言

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_zonelimit_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】限流设置的基本应用介绍,希望对你有所帮助!

### Nginx限流配置教程 Nginx 提供了一个模块 `ngx_http_limit_req_module` 来实现请求速率限制的功能。此模块的核心在于定义一个共享内存区用来存储会话状态,并通过指定的键(如 IP 地址)来跟踪请求频率。 #### 配置步骤说明 1. **创建共享内存区域** 使用 `limit_req_zone` 指令可以定义一个共享内存区域,用于保存访问者的状态信息。例如,基于客户端 IP 地址进行限流时,可按如下方式设置: ```nginx http { limit_req_zone $binary_remote_addr zone=mylimit:10m rate=2r/s; } ``` 这里 `$binary_remote_addr` 是指客户端的二进制形式 IP 地址,`zone=mylimit:10m` 定义名为 `mylimit` 的共享内存区域大小为 10MB,而 `rate=2r/s` 则表示每秒允许的最大请求数为 2次[^1]。 2. **应用流量限制到具体位置** 单独定义 `limit_req_zone` 并不会实际生效,还需要配合 `limit_req` 指令将其作用于具体的 location 或 server 块中。下面是一个针对 `/login/` 路径实施限流的例子: ```nginx server { listen 80; location /login/ { limit_req zone=mylimit burst=5 nodelay; proxy_pass http://backend_server; } } ``` 上述配置中的 `burst=5` 参数意味着当超过设定速率时,额外最多允许排队等待处理的请求数量为 5;`nodelay` 取消延迟机制,使得超出部分立即被处理而不是逐步释放队列中的请求[^2]。 3. **验证效果并调整优化** 配置完成后,可通过分析日志文件确认限流策略是否正常工作。默认情况下,Nginx 日志路径可能位于 `/var/log/nginx/access.log` 和 `/var/log/nginx/error.log` 中。如果希望更直观地观察性能指标变化,则推荐集成 Prometheus 和 Grafana 等监控平台来进行可视化展示[^3]。 4. **深入理解原理** 尽管表面上看设置了固定的速率比如 `rate=2r/s` ,实际上内部是以毫秒级精度控制请求间隔时间。对于本例而言,“2 请求/秒”的含义转换成了“每隔至少 500ms 才能接受下一个新请求”。一旦违反这个规则即触发限流响应[^4]。 ```python # 示例 Python脚本模拟压力测试场景下的表现评估(仅作参考用途) import time, requests url = 'http://example.com/login/' for i in range(10): try: resp = requests.get(url) print(f'Request {i}: Status Code={resp.status_code}') except Exception as e: print(e) finally: time.sleep(.1) # 控制发送速度接近理论阈值附近便于观测行为差异 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宥钧

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值