报错是这么冒出来的。CentOS 7.9 上用 nginx 给接口加了限流,rate 设成 10r/s,活动开始后大量正常用户收到 503,日志里全是 limiting requests,实际 QPS 只有峰值的三分之一。
中间走过弯路,把「nodelay 没开,请求被排队而不是直接放行,前端超时后重试进一步放大」当成主因,改完现象没变。
原因不止一个,得分开看。burst 设得太小,用户打开页面同时发十几个静态请求就被判为超限。少数情况下是limit_req_zone 的 key 用了 $remote_addr,公司出口 NAT 后整个办公室共用一个桶。
少数情况下是限流写在 location 上,静态资源和接口共用一个 zone。
第一件事是看限流日志的比例
grep -c 'limiting requests' /var/log/nginx/error.log
给 zone 加 burst 并开 nodelay
printf 'limit_req_zone $binary_remote_addr zone=api:10m rate=20r/s;\n' > /etc/nginx/conf.d/limit.conf
然后在接口 location 里引用并留突发额度
printf 'limit_req zone=api burst=50 nodelay;\nlimit_req_status 429;\n' > /etc/nginx/conf.d/limit_use.conf
剩下的就是按 URI 单独划分桶,静态资源不限
nginx -T | grep -n 'limit_req' && nginx -s reload
怎么算真的好了,看的是同一批现象。压测下正常请求的 429 比例降到千分之一以下,grep limiting requests 的数量随 QPS 线性而不是陡增,接口 P99 保持稳定。
这里还有个坑。burst 是允许的突发排队数,配合 nodelay 才是平滑放行;key 用 $binary_remote_addr 比 $remote_addr 省内存,但 NAT 场景要换成带用户标识的变量。这类问题最好一次改到位,反复小改反而容易把原因搅混。
