乐闻世界logo
搜索文章和话题

Nginx 如何实现限流?有哪些限流策略?

2月21日 16:57

Nginx 如何实现限流?有哪些限流策略?

Nginx 提供了强大的限流功能,可以有效防止 DDoS 攻击、保护服务器资源、防止恶意请求。Nginx 的限流主要通过 limit_reqlimit_conn 模块实现。

请求速率限制(limit_req):

nginx
http { # 定义限流区域,基于客户端 IP limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s; # 定义限流区域,基于请求 URI limit_req_zone $request_uri zone=uri:10m rate=5r/s; # 定义限流区域,基于服务器名称 limit_req_zone $server_name zone=server:10m rate=100r/s; server { listen 80; server_name example.com; # 应用限流 location / { limit_req zone=one burst=20 nodelay; proxy_pass http://backend; } # API 接口限流 location /api/ { limit_req zone=one burst=10 nodelay; limit_req_status 429; proxy_pass http://api_backend; } } }

参数说明:

  1. limit_req_zone:定义限流区域

    • $binary_remote_addr:客户端 IP 地址(二进制格式,节省内存)
    • zone=one:10m:区域名称和共享内存大小(10M 可存储约 16 万个 IP)
    • rate=10r/s:每秒允许 10 个请求
  2. limit_req:应用限流规则

    • zone=one:使用的限流区域
    • burst=20:允许的突发请求数
    • nodelay:不延迟处理突发请求
  3. limit_req_status:超过限制时返回的状态码(默认 503)

连接数限制(limit_conn):

nginx
http { # 定义连接数限制区域 limit_conn_zone $binary_remote_addr zone=addr:10m; # 定义服务器连接数限制区域 limit_conn_zone $server_name zone=server:10m; server { listen 80; server_name example.com; # 限制每个 IP 的并发连接数 limit_conn addr 10; # 限制服务器的总连接数 limit_conn server 1000; location / { proxy_pass http://backend; } } }

带宽限制:

nginx
server { listen 80; server_name example.com; location /download/ { # 限制下载速度为 1MB/s limit_rate 1m; # 前 10MB 不限速 limit_rate_after 10m; root /var/www/files; } }

综合限流配置:

nginx
http { # 请求速率限制 limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s; limit_req_zone $request_uri zone=uri_limit:10m rate=5r/s; # 连接数限制 limit_conn_zone $binary_remote_addr zone=conn_limit:10m; # 状态码限制 limit_req_status 429; limit_conn_status 429; server { listen 80; server_name example.com; # 全局限流 limit_conn conn_limit 10; # 首页限流 location = / { limit_req zone=req_limit burst=20 nodelay; proxy_pass http://backend; } # API 接口严格限流 location /api/ { limit_req zone=req_limit burst=5 nodelay; limit_req zone=uri_limit burst=2 nodelay; proxy_pass http://api_backend; } # 下载限速 location /download/ { limit_rate 1m; limit_rate_after 10m; root /var/www/files; } # 静态资源不限流 location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2)$ { root /var/www/static; } } }

白名单配置:

nginx
http { # 定义限流区域 limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s; # 定义白名单 geo $limit_key { default $binary_remote_addr; 192.168.1.0/24 ""; 10.0.0.0/8 ""; } # 基于白名单的限流 limit_req_zone $limit_key zone=whitelist_limit:10m rate=10r/s; server { listen 80; server_name example.com; location / { limit_req zone=whitelist_limit burst=20 nodelay; proxy_pass http://backend; } } }

动态限流:

nginx
http { # 根据请求方法限流 map $request_method $limit_key { default $binary_remote_addr; GET ""; HEAD ""; } limit_req_zone $limit_key zone=dynamic_limit:10m rate=10r/s; server { listen 80; server_name example.com; location / { limit_req zone=dynamic_limit burst=20 nodelay; proxy_pass http://backend; } } }

限流日志:

nginx
http { # 自定义日志格式,包含限流信息 log_format limit '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" ' 'rt=$request_time limit=$limit_req_status'; access_log /var/log/nginx/access.log limit; # 限流区域 limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s; server { listen 80; server_name example.com; location / { limit_req zone=req_limit burst=20 nodelay; limit_req_log_level warn; proxy_pass http://backend; } } }

限流策略选择:

  1. 固定窗口限流rate=10r/s,每秒固定请求数
  2. 滑动窗口限流:通过 burst 参数实现
  3. 令牌桶算法:Nginx 默认使用,允许突发流量
  4. 漏桶算法:通过 nodelay 参数控制

实际应用场景:

1. API 接口限流:

nginx
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/min; location /api/ { limit_req zone=api_limit burst=10 nodelay; limit_req_status 429; add_header X-RateLimit-Limit "100"; add_header X-RateLimit-Remaining "90"; add_header X-RateLimit-Reset "60"; proxy_pass http://api_backend; }

2. 登录接口限流:

nginx
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=5r/min; location /login { limit_req zone=login_limit burst=2 nodelay; limit_req_status 429; proxy_pass http://auth_backend; }

3. 文件下载限速:

nginx
location /download/ { limit_rate 500k; limit_rate_after 5m; root /var/www/files; }

4. 防止暴力破解:

nginx
limit_req_zone $binary_remote_addr zone=auth_limit:10m rate=3r/min; location ~* ^/(login|register|reset-password) { limit_req zone=auth_limit burst=1 nodelay; limit_req_status 429; proxy_pass http://auth_backend; }

监控和调试:

nginx
# 启用限流状态监控 location /limit_status { limit_req_status 429; add_header Content-Type text/plain; return 200 "Rate limit status: $limit_req_status"; } # 查看限流统计 location /nginx_status { stub_status on; access_log off; allow 127.0.0.1; deny all; }

最佳实践:

  1. 合理设置速率:根据业务需求设置合理的限流速率
  2. 使用 burst:允许一定程度的突发流量
  3. 返回友好错误:设置 429 状态码,返回友好提示
  4. 白名单机制:对可信 IP 放开限流
  5. 监控限流效果:定期检查限流日志,调整策略
  6. 分层限流:对不同接口设置不同的限流策略
  7. 结合缓存:对静态资源使用缓存,减少限流压力

性能考虑:

  1. 共享内存大小:根据 IP 数量合理设置 zone 大小
  2. 限流粒度:选择合适的限流键(IP、URI 等)
  3. 日志级别:生产环境使用 warn 级别,减少日志量
  4. nodelay 使用:根据场景选择是否使用 nodelay
标签:Nginx