直接答案:429 表示请求超过某层允许的速率或配额,可能由 CDN/WAF、Nginx、API 网关或应用返回。先用响应头、边缘事件、Nginx $limit_req_status 和应用日志确认生成层,再检查限流键是否用了真实客户端 IP、用户/API key 或接口维度。若所有用户在代理后都显示成一个地址,按 IP 限流会把全站当成一个人。合理设置 rate、burst、延迟/拒绝策略和 Retry-After,客户端采用带抖动的退避,不能无限立即重试。
本文处理正常用户误遇 429、爬虫/接口突发被限流,以及上线新规则后错误率升高。若 CPU、数据库或上游已经过载,限流是保护措施而非根因修复;应同时处理容量和慢请求。
本文按 2026 年 9 月可查的官方文档核对。示例命令以只读取证为主;凡涉及删除、覆盖、重启、权限、网络或数据库参数的动作,都应先确认操作对象、备份、维护窗口和带外恢复入口。不同发行版与软件版本的路径可能不同,必须先查询实际配置再改。
先用证据判断故障在哪一层
| 现象或检查点 | 它能说明什么 | 直接证据 | 不要误判为 |
|---|---|---|---|
| 响应含边缘规则标识 | CDN/WAF 在源站前拒绝 | 规则ID、Ray/request ID与事件 | Nginx limit_req |
| $limit_req_status=REJECTED | 命中 Nginx 限流区 | zone、key、rate 与请求路径 | 应用配额 |
| 登录用户才429 | 账号、API key或业务额度 | 用户ID与应用审计 | 同IP用户共享 |
| 公司/校园网大量误伤 | NAT 下多人共享公网IP | 真实IP与用户维度分布 | 单个恶意客户端 |
| 客户端重试后流量更高 | 无退避造成重试风暴 | 429后请求间隔与Retry-After | 服务器自动恢复 |
这张表的用法不是“看到一个关键词就改一个参数”,而是把客户端、DNS或边缘、Web 代理、应用、数据层依次分开。至少保留故障时间、完整 URL、状态码、关键响应头、同一时刻的服务日志和一份正常样本。只有时间能够对齐,才能判断两个现象是否属于同一次故障。
六步排查与修复顺序
1. 确认谁返回 429
保存状态、响应头、正文、时间、URL、方法、用户和 request ID。查看 CDN 事件、Nginx 日志与应用审计;源站未收到请求则从边缘查,Nginx 放行而应用返回 429 则查业务配额。
2. 验证真实客户端身份
若前面有 CDN/负载均衡,只信任官方或受控代理网段传来的真实 IP,再设置 real_ip。未验证来源时直接信任 X-Forwarded-For,攻击者可伪造地址绕过或嫁祸他人。
3. 选择符合业务的限流键
匿名公开接口可按 IP 与路径,登录接口可叠加账号,API 可按 key/租户;NAT、IPv6 前缀、移动网络和爬虫都影响公平性。昂贵接口的限制应比静态资源更严格。
4. 在 dry run 中测 rate 与 burst
先记录而不拒绝,观察正常用户的请求分布、突发长度和高峰。rate 控制平均速率,burst 接纳短时队列,nodelay 改变处理方式;不能只复制一组 1r/s 数字。
5. 返回可操作的失败信息
对 API 返回稳定 429、错误码和适当 Retry-After,客户端使用指数退避加随机抖动。对登录等安全接口不要透露账号是否存在;对幂等写操作使用幂等键,避免重试重复扣款或创建。
6. 上线后同时看保护与转化
小流量启用规则,监控 429 比例、被限用户、源站 CPU/数据库、p95/p99、登录/下单成功率和攻击流量。既要证明过载下降,也要证明正常用户没有被共享 IP 大面积误伤。
可复制的只读取证命令
以下命令中的域名、服务名、路径和时间范围要替换为自己的真实值。先执行查询命令并保存原始输出;不要把“命令能运行”误当成“业务已恢复”。
text
curl -sS -D - -o /dev/null https://www.your-domain.tld/api/resource
nginx -T 2>&1 | grep -nE 'limit_req_zone|limit_req |limit_req_status|real_ip'
grep ' 429 ' /var/log/nginx/access.log | tail -n 50
awk '$9==429 {print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head
curl -sS -o /dev/null -w '%{http_code} %{time_total}\n' https://www.your-domain.tld/api/resource
curl -sS -D - -o /dev/null https://www.your-domain.tld/api/resource:保存429响应头与Retry-After等证据nginx -T 2>&1 | grep -nE 'limit_req_zone|limit_req |limit_req_status|real_ip':查看生效限流区、键与真实IP配置grep ' 429 ' /var/log/nginx/access.log | tail -n 50:抽样最近429;实际字段和隐私处理按日志格式调整awk '$9==429 {print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head:粗看来源集中度;有代理时第一列未必是真实客户端curl -sS -o /dev/null -w '%{http_code} %{time_total}\n' https://www.your-domain.tld/api/resource:用受控频率建立正常单请求基线,不要用生产站做压力测试
如命令输出包含公网 IP、用户名、Cookie、令牌、数据库连接串或客户数据,分享工单前先脱敏。对比时保留时间戳、时区和命令本身,否则后来无法复现同一观察条件。
五个最容易扩大故障的误区
- 直接删除所有限流:可能让攻击或突发流量把应用和数据库拖垮。
- 代理后仍按 remote_addr 限流:所有用户可能共享 CDN 回源地址而被整体误伤。
- 无条件信任 X-Forwarded-For:客户端可伪造,限流和审计都会失真。
- 客户端收到429立即无限重试:会形成自激式重试风暴。
- 只看429下降:如果规则被关闭但源站开始500,整体可用性反而更差。
变更、回滚与数据边界
上线前导出边缘/Nginx规则并记录 dry-run 基线。若正常用户转化、登录或关键 API 成功率越过停止阈值,恢复上一规则或降低作用范围,同时保留对明显攻击路径的保护。回滚限流后必须确认源站容量能承受恢复流量;对已经排队或重试的写请求检查幂等和重复数据,不能仅看状态码恢复。
如果只能先恢复服务、还不能确认根因,应把措施标记为“临时缓解”,例如限流、摘除单节点、切回上一配置或临时绕过一层代理。恢复后仍要在受控环境复现原因,并验证同类故障不会在下一次重启、发布或高峰重新出现。
统一验收清单
- [ ] 429 生成层已确认
- [ ] 真实IP只信任受控代理
- [ ] 限流键与业务身份匹配
- [ ] rate与burst来自真实基线
- [ ] 正常突发和恶意持续流量已区分
- [ ] API提供合理Retry-After或退避说明
- [ ] 小流量上线后转化未显著下降
- [ ] 源站资源与尾延迟得到保护
验收必须同时覆盖机器内部和真实外部路径。首页返回 200 不能证明上传、长连接、登录、数据库写入或移动端都正常;同样,控制台显示“运行中”也不能证明应用已能处理请求。至少选一个正常请求、一个边界请求和一个失败请求,记录预期与实际结果。
相关内容与隔离测试入口
建议先阅读CDN、WAF和高防区别、服务器CPU 100%、服务器日志保留,把本问题放回完整请求链路。若生产环境不适合直接试验,可查看美国弹性云服务器的当前规格与库存,搭建与生产隔离的复现环境;测试机不能替代生产备份,价格、库存和可选配置以实时产品页为准。
常见问题
Nginx limit_req 默认返回 429 吗?
官方模块默认拒绝状态可为 503,可用 limit_req_status 配置。无论选择何码,都要与应用、监控和客户端约定一致。
burst 越大越好吗?
不是。它容纳短时突发,也会增加排队、内存或瞬间放行压力;应按用户行为和下游容量测定。
搜索引擎爬虫遇到429怎么办?
先验证来源并优化抓取/缓存,不应仅凭User-Agent无限放行。持续429会降低抓取效率,应在站长平台和日志中验证。
429 与 WAF 封禁有什么区别?
429通常表达速率/配额,WAF也可能自定义返回其他4xx。必须看规则ID、正文和生成层。
Retry-After 应写秒还是日期?
HTTP 标准允许相应格式,客户端兼容性需验证。API常用秒数,并配合指数退避和随机抖动。