插件窝 干货文章 nginx限流怎么解决

nginx限流怎么解决

limit zone Nginx req 228    来源:    2025-04-07

Nginx限流解决方案

Nginx提供了多种限流机制来保护服务器免受过多请求的冲击。以下是几种主要的限流方法及其实现方式:

1. 基于连接数的限流 (ngx_http_limit_conn_module)

http {
    limit_conn_zone $binary_remote_addr zone=addr:10m;

    server {
        location / {
            limit_conn addr 10;  # 每个IP最多10个并发连接
        }
    }
}

2. 基于请求速率的限流 (ngx_http_limit_req_module)

http {
    limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;

    server {
        location / {
            limit_req zone=one burst=20 nodelay;
            # rate=10r/s 表示每秒10个请求
            # burst=20 表示允许突发20个请求
            # nodelay 表示不延迟处理突发请求
        }
    }
}

3. 基于带宽的限流 (ngx_http_core_module)

location /download/ {
    limit_rate 100k;  # 限制下载速度为100KB/s
    limit_rate_after 1m;  # 前1MB不限速
}

4. 高级限流配置

4.1 不同URL路径不同限流策略

http {
    limit_req_zone $binary_remote_addr zone=api:10m rate=5r/s;
    limit_req_zone $binary_remote_addr zone=static:10m rate=100r/s;

    server {
        location /api/ {
            limit_req zone=api burst=10;
        }

        location /static/ {
            limit_req zone=static burst=50;
        }
    }
}

4.2 白名单设置

geo $limit {
    default 1;
    10.0.0.0/8 0;
    192.168.0.0/24 0;
}

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

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

5. 动态限流 (结合Lua脚本)

location / {
    access_by_lua_block {
        local limit_req = require "resty.limit.req"
        local lim, err = limit_req.new("my_limit_req_store", 10, 20)
        if not lim then
            ngx.log(ngx.ERR, "failed to instantiate a resty.limit.req object: ", err)
            return ngx.exit(500)
        end

        local key = ngx.var.binary_remote_addr
        local delay, err = lim:incoming(key, true)
        if not delay then
            if err == "rejected" then
                return ngx.exit(503)
            end
            ngx.log(ngx.ERR, "failed to limit req: ", err)
            return ngx.exit(500)
        end

        if delay >= 0.001 then
            ngx.sleep(delay)
        end
    }
}

6. 限流后的处理

limit_req_status 429;  # 默认是503,可以改为429(Too Many Requests)

error_page 429 /429.html;
location = /429.html {
    internal;
    root /usr/share/nginx/html;
}

最佳实践建议

  1. 合理设置限流阈值:根据业务需求和服务器性能设置
  2. 分层限流:结合应用层、Nginx层和网络层的限流
  3. 监控与调整:使用Nginx日志和监控工具持续观察限流效果
  4. 灰度发布:新限流策略先在部分服务器上测试
  5. 考虑用户体验:为被限流的请求提供友好的错误页面

通过以上方法,可以有效防止服务器因突发流量而过载,同时保证正常用户的访问体验。