nginx限流需分清limit_req(控请求数)、limit_conn(控并发连接数)、limit_rate(控响应速度)三者机制不同、生效时机与配置位置各异,混用易导致请求失败。

直接说结论:Nginx限流不是“开个开关”就完事,必须分清是控请求数(limit_req)、控并发连接数(limit_conn),还是控响应下载速度(limit_rate)——三者机制不同、生效时机不同、配置位置也不同,混用会相互干扰甚至导致请求失败。
怎么配 limit_req 才不卡住用户?
这是最常用也最容易翻车的限流方式,核心是令牌桶算法:每秒按 rate 填充令牌,请求来时取一个;没令牌就排队(burst)或直接拒(加 nodelay)。
-
burst不是“允许超速”,而是“最多能缓存几个等处理”,比如burst=10意味着第 11 个超速请求才会被拒绝,但前 10 个仍要排队等令牌释放 - 不加
nodelay时,排队请求会被延迟转发,用户感知就是“卡顿”甚至超时;加了nodelay就变成“有令牌立刻放行,没令牌立刻 503”,更接近硬限流 -
rate单位支持r/s(每秒)和r/m(每分钟),但注意1r/m≠ “每分钟只让过 1 个”,而是“平均每 60 秒 1 个”,实际可能集中在某几秒爆发 - 测试时别用
curl单次发多个请求,要用ab -c10 -n100或wrk模拟真实并发,否则看不出burst效果
limit_conn 为什么有时完全不起作用?
这个模块限制的是 TCP 连接数,不是 HTTP 请求。它只在 Nginx 完成 request header 解析、准备把请求交给 upstream 时才计数,所以静态文件(如图片、CSS)走 Nginx 自身服务时,limit_conn 是不生效的。
- 必须搭配
limit_conn_zone使用,且 key 推荐用$binary_remote_addr(比$remote_addr节省内存) -
limit_conn addr 10表示“每个 IP 最多 10 个并发连接”,但若后端响应慢(比如数据库卡住),这些连接会长时间占用,新请求就会被挂起甚至超时 - 如果同时配了
limit_rate(比如限速 1k),而连接又卡在慢响应上,会导致后续请求因连接数满而直接失败,现象是大量 503 或连接超时,而不是限速提示 - 日志里查不到连接拒绝记录,默认不打日志;要看到效果得加
limit_conn_log_level error;
limit_rate 和 limit_rate_after 怎么配合防“薅羊毛”?
这两个指令专治大文件下载场景,比如视频、安装包。单纯 limit_rate 50k 会让所有请求从头开始就慢,体验差;加 limit_rate_after 就能“先快后慢”。
-
limit_rate_after 1m表示前 1MB 不限速,之后才启用limit_rate限速,适合让用户快速预览开头 - 该指令只对 response body 生效,header 部分不受影响;也不影响 upstream 的处理速度,只是 Nginx 向客户端吐数据变慢
- 注意单位:
limit_rate 100k是每秒约 100KB,不是 100KiB;实测中受系统缓冲区、TCP 窗口大小影响,实际速率会有浮动 - 不能放在
http块顶层,必须在server或location里,且对 proxy_pass 流量也生效(即限的是 Nginx 到 client 的下行带宽)
真正难的不是写对这几行配置,而是搞清你到底想拦什么:是防爬虫高频刷接口(limit_req),还是防慢速攻击耗尽连接(limit_conn),或是控制带宽成本(limit_rate)。三者叠加时,务必验证它们的生效顺序和冲突点——比如 limit_conn 拒绝了连接,limit_req 根本就没机会运行。










