nginx应对促销流量需柔性限流:用limit_req_zone+limit_req搭配burst与合理key(如$host、$cookie_uid),按域名/路径分层限流,设置充足burst缓冲,区分用户粒度,并通过日志与监控验证效果。

Nginx 应对促销活动突发流量,关键不是“一刀切”拒绝请求,而是用柔性限流把洪峰削平、让合法用户尽量能进得来、系统稳得住。核心是围绕 limit_req_zone + limit_req 搭配 burst 和合理 key 选型,而不是只设个 rate=10r/s 就完事。
按域名做独立限流,避免互相干扰
促销接口通常走独立子域(如 promo.example.com)或路径(如 /api/promo/)。优先用 $host 做 key,确保活动流量不影响主站:
http {
limit_req_zone $host zone=promohost:10m rate=500r/s;
limit_req_zone $host$uri zone=promopath:10m rate=30r/s;
}
server {
server_name promo.example.com;
location /api/ {
limit_req zone=promohost burst=1000 nodelay;
}
location /api/promo/order {
limit_req zone=promopath burst=200;
}
}
这样:整个域名每秒最多放行 500 请求(含缓冲 1000),而下单接口单独再卡一层——每秒 30 个,每个 URI 路径单独计数,防止单一接口被刷爆。
给 burst 留足缓冲空间,别让 503 成常态
促销瞬间 QPS 可能翻几十倍。burst 不是随便填的数字,它代表“允许排队等待的请求数”。例如日常峰值 200 QPS,预估大促峰值 2500 QPS,那 burst=2300 是底线:
-
burst=2300配合rate=200r/s,意味着最多缓存 2300 个请求,Nginx 会以 200/s 的速度慢慢消化 - 不加
nodelay:超限请求进入队列,用户感知为轻微延迟(可接受) - 加
nodelay:队列满后立刻 503,适合强一致性场景(如库存扣减前校验),但慎用
区分用户粒度,保护核心路径
单纯按 IP 限流在 CDN 或 NAT 环境下容易误伤。对登录、下单、领券等高危路径,建议组合 key:
limit_req_zone $binary_remote_addr$http_x_forwarded_for zone=userip:10m rate=5r/s; limit_req_zone $cookie_uid zone=userid:10m rate=10r/s;
然后在对应 location 中启用:
location /api/promo/coupon {
limit_req zone=userid burst=50;
limit_req zone=userip burst=5;
}
既支持登录态用户($cookie_uid)每秒 10 次、最多缓 50 次,也兜底限制未登录 IP 每秒最多 5 次。
配合日志与监控,快速验证效果
在 server 块中加一行日志,专门记录被限流的请求:
log_format limitlog '$remote_addr - $host [$time_local] "$request" $status $limit_rate_limit $limit_rate_burst'; access_log /var/log/nginx/promo-limit.log limitlog;
再配合 Prometheus + nginx-vts-exporter,实时看 limit_requests_rejected 和 limit_requests_delayed 指标——如果 rejected 持续飙升,说明 burst 太小或 rate 设低了;如果 delayed 过高,说明后端处理变慢,需排查上游。
不复杂但容易忽略











