微信公众号
扫描关注微信公众号
博客大厅

如何限制 Nginx 的访问频率?

原创 来源:博客站 阅读 0 今天 07:36:25 听全文

在 Nginx 中限制访问频率(请求速率或并发连接数)可以有效防止恶意刷请求、DDoS 攻击或过载后端服务。以下是详细的配置方法和场景示例:


一、限制请求速率(Rate Limiting)

1. 基于 IP 限制每秒请求数

http {
    # 定义限流规则(10MB 内存存储计数,每秒允许 10 请求)
    limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;

    server {
        listen 80;
        server_name example.com;

        # 应用限流规则(突发请求不超过 20)
        location /api/ {
            limit_req zone=req_limit burst=20 nodelay;
            proxy_pass http://backend;
        }
    }
}
  • 参数说明
    • limit_req_zone:定义共享内存区(zone)和速率(rate)。
      • $binary_remote_addr:以客户端 IP 作为限流键。
      • zone=req_limit:10m:分配 10MB 内存存储计数状态(约可记录 16 万 IP)。
      • rate=10r/s:每秒允许 10 请求(或使用 60r/m 表示每分钟 60 次)。
    • limit_req:应用限流规则。
      • burst=20:允许突发 20 请求(超出速率的请求排队等待)。
      • nodelay:立即处理突发请求,但不突破总体速率限制(若无此参数,突发请求会被延迟处理)。

2. 按 URL 路径差异化限流

limit_req_zone $binary_remote_addr zone=api_limit:10m rate=5r/s;
limit_req_zone $binary_remote_addr zone=static_limit:10m rate=20r/s;

location /api/ {
    limit_req zone=api_limit burst=10;
    proxy_pass http://backend;
}

location /static/ {
    limit_req zone=static_limit burst=30;
    root /var/www;
}

二、限制并发连接数(Connection Limiting)

1. 限制单个 IP 的并发连接数

http {
    # 定义并发连接限制区(10MB 内存,键为客户端 IP)
    limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

    server {
        listen 80;
        server_name example.com;

        # 每个 IP 最多 5 个并发连接
        location /download/ {
            limit_conn conn_limit 5;
            limit_rate 100k;  # 限速 100KB/s(可选)
            root /var/www;
        }
    }
}
  • 关键指令
    • limit_conn_zone:定义共享内存区。
    • limit_conn:设置每个键(如 IP)的最大并发连接数。
    • limit_rate:限制单个连接的下载速度(可选)。

2. 限制整个服务的总并发连接数

events {
    worker_connections 1024;  # 单个 Worker 的最大连接数
}

http {
    server {
        listen 80;
        server_name example.com;
        # 全局限制(需结合 worker_processes 计算)
    }
}
  • 总并发 = worker_processes × worker_connections

三、高级场景配置

1. 白名单排除(不限制内网 IP)

geo $limit {
    default 1;
    192.168.1.0/24 0;  # 内网 IP 不限速
}

map $limit $limit_key {
    0 "";
    1 $binary_remote_addr;
}

limit_req_zone $limit_key zone=req_limit:10m rate=10r/s;

location / {
    limit_req zone=req_limit burst=20;
    proxy_pass http://backend;
}

2. 结合 User-Agent 限制爬虫

map $http_user_agent $is_bot {
    default 0;
    "~*(Googlebot|Bingbot)" 1;
}

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

location / {
    limit_req zone=bot_limit burst=5 if=$is_bot;
    proxy_pass http://backend;
}

四、验证与调试

1. 测试限流效果

# 模拟高并发请求(10 线程,共 100 请求)
ab -n 100 -c 10 http://example.com/api/

# 查看被拒绝的请求(日志路径见 error_log)
tail -f /var/log/nginx/error.log
  • 触发限流时,日志会记录 503 (Service Temporarily Unavailable) 错误。

2. 监控限流状态

location /status {
    stub_status on;
    allow 127.0.0.1;
    deny all;
}
  • 访问 http://localhost/status 查看当前连接数和请求状态。

五、注意事项

  1. 内存分配

    • limit_req_zone10m 可存储约 16 万 IP 状态,根据业务规模调整。
  2. 突发流量处理

    • burst 参数允许短暂超限,但需权衡服务承受能力。
  3. 日志记录

    • 被限流的请求默认记录到 error_log,建议单独监控:
      limit_req_status 429;  # 自定义返回状态码(默认 503)
      access_log /var/log/nginx/rate_limited.log combined;
      
  4. 分布式限流

    • 若 Nginx 前置有负载均衡,需改用 $http_x_forwarded_for 替代 $binary_remote_addr

完整配置示例

http {
    # 定义限流规则
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
    limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

    server {
        listen 80;
        server_name example.com;

        # API 限流:每秒 10 请求,突发 20
        location /api/ {
            limit_req zone=api_limit burst=20 nodelay;
            limit_conn conn_limit 5;  # 每个 IP 最多 5 并发
            proxy_pass http://backend;
        }

        # 静态文件限速下载
        location /download/ {
            limit_conn conn_limit 3;  # 每个 IP 最多 3 并发
            limit_rate 500k;          # 限速 500KB/秒
            root /var/www;
        }
    }
}

通过以上配置,可有效防护恶意请求,同时保障正常用户的访问体验。

学在每日,进无止境!更多精彩内容请关注微信公众号。
原文出处: 内容由AI生成仅供参考,请勿使用于商业用途。如若转载请注明原文及出处。
出处地址:http://www.07sucai.com/tech/965.html
版权声明:本文来源地址若非本站均为转载,若侵害到您的权利,请及时联系我们,我们会在第一时间进行处理。
>