如何解决 429 “请求过多” 错误

热门:
升级您的服务器配置! 申请 AVA 并使用 立减 15%
使用优惠码:

如何解决 429 “请求过多” 错误

HTTP 429 “请求过多” 错误是由 server 在用户(或客户端)在给定时间范围内超过允许请求次数时发送的限流响应代码。此状态通常是安全、API 保护或 anti-DDoS 机制的一部分。

在生产环境中,它可能会中断服务、破坏 API 集成或影响 SEO。本高级指南介绍如何从诊断、预防和解决 429 错误,涵盖客户端和服务端两个角度。

 是什么导致 429 错误?

常见场景:

  • 用户/bot 发送了过多 HTTP 请求(API 调用、页面加载等)

  • 你的应用正在过于激进地抓取或轮询第三方服务

  • Web application firewalls (WAFs) 或反向代理(例如 Cloudflare、Nginx)强制执行速率限制

  • server 或后端 API 使用 rate-limiting libraries(例如 express-rate-limit、mod_evasive 等)

  • bot 或爬虫淹没了网站或端点

 步骤 1:识别来源

✅ 1. 检查响应头

server 通常会在 429 响应中发送 Retry-After 头:

HTTP/1.1 429 Too Many Requests
Retry-After: 60

这会告诉客户端在再次尝试之前需要等待多长时间(以秒为单位)。

✅ 2. 检查访问日志

对于 Apache:

cat /var/log/apache2/access.log | grep "429"

对于 Nginx:

cat /var/log/nginx/access.log | grep "429"

这有助于识别哪些 IP 或端点触发了限制。

✅ 3. 使用监控工具

  • Fail2Ban logs

  • Cloudflare Firewall Events

  • Application-level logs(Laravel、Express、Django 等)

  • 速率限制分析(如果使用 API gateway)

 步骤 2:服务端修复

 A. Nginx Rate Limiting(如果已启用)

Nginx 可能会配置成这样:

limit_req_zone $binary_remote_addr zone=api_limit:10m rate=5r/s;
location /api/ {
limit_req zone=api_limit burst=10 nodelay;
}

解决方案:

  • 提高 rateburst

  • 仅应用于特定路径(例如 /api/),而不是全局

  • 将已知内部 IP 加入白名单

 B. Apache (mod_evasive or mod_security)

如果 mod_evasive 处于活动状态:

sudo nano /etc/apache2/mods-enabled/evasive.conf

调整:

DOSPageCount 10
DOSSiteCount 100
DOSBlockingPeriod 10

➡️ 提高阈值或对特定受信任 IP 禁用。

 C. Cloudflare / CDN Rules

如果你位于 Cloudflare 后面,请检查:

  • Rate Limiting Rules 位于 Security > WAF

  • Bot Fight Mode

  • Firewall Rules 基于 User-Agent 或 IP 进行阻止

解决方案:

  • 降低敏感度

  • 将 server IP 或某些 user agents 加入白名单

  • 为安全爬虫和合作伙伴创建自定义规则

D. Application-Level Rate Limiting

检查你的应用是否使用以下库强制限制:

  • Node.js: express-rate-limit

  • Laravel: ThrottleRequests

  • Django: drf-extensions or middleware

更新配置,例如:

rateLimit({
windowMs: 1 * 60 * 1000, // 1 minute
max: 100, // limit each IP to 100 requests per minute
})

➡️ 根据 auth tokens 调整限制、添加 user/IP 白名单,或提高配额。

 步骤 3:客户端修复(在消费 API 时)

如果你的应用是客户端并收到 429:

✅ 实现指数退避

自动重试请求,并逐渐增加延迟:

const retryAfter = (attempt) => Math.pow(2, attempt) * 1000;

✅ 遵守 Retry-After 头

if (response.status === 429) {
const wait = response.headers['retry-after'] * 1000;
setTimeout(() => retryRequest(), wait);
}

✅ 为客户端添加 Rate-Limiting

如果是轮询,请限制你自己的请求:

// Use lodash or custom throttling
_.throttle(() => fetchData(), 1000);

步骤 4:SEO 考量

search engine crawlers 提供 429 状态可能会损害你的排名。

✅ 解决方案:

  • 改为返回带有 Retry-After 的 503(Service Unavailable)

  • 使用 robots.txt 限制爬取速率:

    User-agent: *
    Crawl-delay: 10
  • 在 Cloudflare 中:前往 Bots > Crawl Management

 步骤 5:在不阻止合法用户的情况下进行保护

不要使用过于严厉的 429 限制:

  • 对可疑活动使用 CAPTCHAs

  • 实施 progressive delays,而不是硬性阻止

  • 对已登录用户使用基于 user-based 而不是基于 IP 的速率限制

  • authenticated access 提供更高的速率限制(例如,通过 API keys 或 tokens)

 结论

429 Too Many Requests 错误是一个有用但有时会造成干扰的工具。了解它来自哪里——server、CDN 还是 application——是解决它的关键。通过正确的配置、日志记录以及客户端对限制的尊重,你可以在保护性和可用性之间取得平衡。