验证nginx防刷限流需四步:一、用hey等工具模拟高并发,观察503/429响应码及access log中$limit标记;二、检查limit_req_zone共享内存使用率,避免因zone不足导致限流失效;三、抓包验证burst与nodelay实际行为;四、压测真实业务流量下是否精准拦截、排队、降级且不误伤正常用户。

验证生产环境中的 Nginx 防刷限流机制,关键不是“测出是否生效”,而是“确认它在真实流量下按预期行为拦截、排队、降级,且不误伤正常用户”。下面分四步讲清楚怎么实打实验证:
一、用工具模拟攻击流量,观察限流响应码与日志
限流是否起作用,最直接的证据是 HTTP 状态码和 access log。
- 对配置了
limit_req的接口(如/api/login),用ab或hey发起高并发请求:hey -n 100 -c 20 http://your-api.com/api/login
若配置为rate=1r/s burst=5 nodelay,应看到约 6–8 个请求返回 200,其余大量返回503(或你设的limit_req_status,如 429)。 - 检查 Nginx access log,确认被限流请求是否带上了
limit_req标记:
在 log_format 中加入$limit变量(需编译支持)或使用$status+ 时间戳组合判断;更简单的是加一条临时日志:log_format limit_log '$remote_addr - $request_time $status $limit_rate'; - 注意区分:返回 503 是因
burst耗尽且无nodelay,返回 429 是你显式设置了limit_req_status 429—— 这两种都算成功拦截。
二、检查共享内存 zone 使用率,避免“假限流”
限流依赖 limit_req_zone 定义的共享内存(zone)。如果内存不足,Nginx 会自动淘汰旧记录,导致限流失效。
- 用
nginx -V确认已启用--with-http_stub_status_module,然后开启 stub_status:location /nginx_status { stub_status on; access_log off; } - 访问
/nginx_status,关注Active connections和Reading/Writing/Waiting,但更重要的是查 zone 占用:
执行sudo nginx -T 2>/dev/null | grep limit_req_zone看定义的 zone 大小(如req_limit:10m);
再用ps aux | grep nginx查 master 进程内存占用趋势,突增可能意味着 zone 频繁回收。 - 经验参考:10MB zone 约可存 16 万 IP(
$binary_remote_addr),若日均 UV 超 50 万,建议调大到20m或按业务分粒度(如加$http_user_agent组合)。
三、抓包看实际行为:burst 和 nodelay 到底怎么工作
很多人配了 burst=20 nodelay 却发现“好像没排队”,其实是误解了漏桶逻辑。
- 用
tcpdump或浏览器开发者工具 Network 面板,对同一 IP 连续发 30 个请求(间隔 若配rate=10r/s burst=20 nodelay,前 20 个会几乎同时通过(不排队),第 21 个开始被 503 拒绝;
若去掉nodelay,前 20 个仍放行,但第 11~20 个会被延迟(response time 明显拉长至 100ms+ 间隔)。 - 重点验证点:
– 是否真按 IP 限流?换不同代理 IP 测试,确认各自独立计数;
– 是否绕过?尝试加随机 query 参数或 header,看是否仍被拦(说明 key 设对了);
– 是否误杀?用白名单 IP(如运维出口 IP)测试,确认没被波及(必要时用geo+map做例外)。
四、线上灰度验证:用真实流量抽样比对
压测再准,也不如真实用户反馈。上线后必须做渐进式验证。
- 先对 5% 流量开启限流(用
split_clients或 upstream 权重分流),对比两组的:
– 接口成功率(限流组 503/429 比例应稳定在预期阈值内);
– 后端 P99 延迟(应明显下降,说明后端压力减轻);
– 错误日志中撞库类关键词(如password、login failed)出现频次是否降低。 - 配合监控看效果:
用 Prometheus + nginx-exporter 抓取nginx_http_requests_total{code=~"429|503"};
设置告警:若 5 分钟内 429 请求突增 300%,且来源集中在某几个 ASN,大概率是真实攻击被拦住了。 - 最后一步:让客服或前端埋点上报“请求失败原因”,若用户侧大量报“操作太频繁”,说明 burst 设置偏小,需要调优而非关限流。











