Skip to content

Nginx ~ 限流

nginx
DNS / CDN

Nginx 网关限流(第一道门)

API 网关限流(第二道门)

服务内部限流(第三道门)

数据库连接池

一、Nginx 限流的两个核心模块

Nginx 限流主要靠两个模块:

✅ 1. 请求频率限流(QPS)

模块:limit_req_module 控制:单位时间请求次数

✅ 2. 连接数限流

模块:limit_conn_module 控制:同时连接数

二、请求频率限流(limit_req)

✅ 基本语法结构

1️⃣ 定义限流规则(http 块)

nginx
http {
    ## 定义一个共享内存区,按 IP 限流
    limit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=10r/s;
}

解释:

  • $binary_remote_addr:按客户端 IP
  • zone=req_limit_per_ip:10m:分配 10MB 内存
  • rate=10r/s:每秒最多 10 个请求

2️⃣ 应用到接口(server 或 location)

nginx
server {
    listen 80;
    server_name api.example.com;

    location /api/ {
        limit_req zone=req_limit_per_ip burst=20 nodelay;
        proxy_pass http://backend;
    }
}

参数说明:

  • burst=20:允许瞬间突发 20 个请求
  • nodelay:不排队,超过直接拒绝
  • 默认返回:429 Too Many Requests

✅ 常见限流组合示例

🌟 场景 1:登录接口限流

nginx
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;

server {
    location /login {
        limit_req zone=login burst=3 nodelay;
        proxy_pass http://auth_service;
    }
}

含义:

每个 IP 每分钟最多 5 次登录请求

🌟 场景 2:按用户 ID 限流(更精准)

nginx
limit_req_zone $arg_userId zone=user_limit:10m rate=20r/m;

URL:

/api/order?userId=123

🌟 场景 3:全站总流量限流

nginx
limit_req_zone $server_name zone=global:20m rate=2000r/s;

location / {
    limit_req zone=global burst=500;
}

🌟 场景 4:防爬虫(UA + IP)

nginx
map $http_user_agent $is_bot {
    default 0;
    ~*curl 1;
    ~*python 1;
    ~*spider 1;
}

limit_req_zone $binary_remote_addr zone=bot:10m rate=2r/s;

server {
    location / {
        if ($is_bot) {
            limit_req zone=bot burst=2 nodelay;
        }
        proxy_pass http://backend;
    }
}

三、连接数限流(limit_conn)

限制同时连接数(防止占满资源)

1️⃣ 定义连接限制

nginx
limit_conn_zone $binary_remote_addr zone=conn_limit_per_ip:10m;

2️⃣ 使用

nginx
location /api/ {
    limit_conn conn_limit_per_ip 5;
    proxy_pass http://backend;
}

含义:

每个 IP 同时最多 5 个连接

四、组合限流(请求数 + 连接数)

nginx
http {
    limit_req_zone $binary_remote_addr zone=req:10m rate=10r/s;
    limit_conn_zone $binary_remote_addr zone=conn:10m;
}

server {
    location /api/ {
        limit_req zone=req burst=20 nodelay;
        limit_conn conn 5;
        proxy_pass http://backend;
    }
}

双保险。

五、返回自定义限流提示页面

nginx
location /api/ {
    limit_req zone=req burst=10;
    error_page 429 = /limit.html;
}

location = /limit.html {
    return 200 "访问过于频繁,请稍后再试";
}

六、限流日志记录(便于监控)

nginx
log_format limit_log '$remote_addr $request_time $status';

access_log /var/log/nginx/limit.log limit_log;

七、分布式限流(Redis + Lua,OpenResty)

如果多台 Nginx:

lua
local key = ngx.var.binary_remote_addr
local redis = require "resty.redis"
local r = redis:new()

r:connect("127.0.0.1", 6379)

local count = r:incr(key)
if count == 1 then
   r:expire(key, 1)
end

if count > 10 then
   ngx.exit(429)
end

Nginx 配置:

nginx
location /api/ {
    access_by_lua_file /etc/nginx/lua/limit.lua;
    proxy_pass http://backend;
}

八、限流调优参数建议表

场景rateburst
登录接口5r/m2
下单接口10r/s5
查询接口50r/s20
爬虫1r/s1
全站2000r/s500

九、限流常见坑

❌ burst 太小 → 正常用户被挡 ❌ rate 太大 → 形同虚设 ❌ 没监控 → 不知道限了谁 ❌ 所有接口同一策略 → 业务崩

十、完整企业级示例配置(可直接用)

nginx
http {
    limit_req_zone $binary_remote_addr zone=api_limit:20m rate=20r/s;
    limit_conn_zone $binary_remote_addr zone=conn_limit:20m;

    server {
        listen 80;

        location /api/ {
            limit_req zone=api_limit burst=40 nodelay;
            limit_conn conn_limit 10;

            error_page 429 = /limit.json;

            proxy_pass http://backend;
        }

        location = /limit.json {
            default_type application/json;
            return 200 '{"code":429,"msg":"请求过于频繁"}';
        }
    }
}

十一、一句话总结 Nginx 限流原理 + 实现

Nginx 限流 = 共享内存计数 + 令牌桶算法 + key 维度(IP/用户) + 规则判断 + 直接拒绝请求