API知识站学习、对比与使用指南
触发限流RPM / TPM / 并发 / 重试

429 Too Many Requests:API 限流、并发过高怎么解决

429 表示请求频率、Token 速率、并发数或短时间突发量超过平台限制。正确做法是降并发、排队、指数退避和减少单次 Token。

排查结论

先用最小请求隔离问题:只保留 API Key、Base URL、模型名和一条 ping 消息。最小请求失败,先修配置;最小请求成功,再回到业务代码排查并发、上下文和部署环境。

1. 问题现象

  • HTTP 状态码返回 429,错误包含 rate limit、Too Many Requests、requests per minute 或 tokens per minute。
  • 单次请求能成功,批量并发、循环任务或多用户同时使用时失败。
  • 短时间连续重试后错误更严重,甚至触发更长时间的冷却。
  • 流式输出前几秒正常,后续大量任务一起启动时开始报错。

2. 最可能原因

并发请求太多,没有队列或限速器。
单次 prompt 太长,输出 max_tokens 太大,触发 TPM 限制。
失败后立即重试,所有请求在同一时间再次打到 API。
免费额度或低等级套餐的 RPM/TPM 很低,不适合批量任务。
多个服务实例共用同一个 Key,但每个实例都以为自己没有超过限制。

3. 快速排查清单

1

区分 RPM 和 TPM

请求次数限制和 Token 限制是两件事;短文本高并发看 RPM,长文本任务通常先撞 TPM。

2

限制并发

先把并发降到 1 到 3 跑通,再逐步增加,记录失败点。

3

使用指数退避和随机抖动

不要固定每秒重试;等待 1s、2s、4s 并加入随机抖动,避免请求同时恢复。

4

减少 max_tokens 和上下文

摘要、分块、缓存系统提示词,避免每个请求都带完整历史。

5

需要稳定吞吐就升级额度

业务确实需要更高吞吐时,升级套餐或申请更高限额,比多 Key 硬绕更可靠。

4. 对应 API 的特殊情况

OpenAI

错误信息可能区分 rate_limit_exceeded 和 insufficient_quota。前者是限速,后者是余额或额度问题。

Gemini

免费层通常同时有分钟级和日级限制;开发环境要把批量任务拆小。

DeepSeek / Kimi / 通义千问

国内平台常按套餐、账号等级或资源包设置并发和速率,控制台一般能看到限制说明。

Claude

长上下文和大输出更容易撞 Token 速率限制;建议开启流式输出并减少无用上下文。

5. 可复制的修复示例

TypeScript 指数退避重试 429
typescript
async function callWithRetry<T>(fn: () => Promise<T>, maxRetries = 4): Promise<T> {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error: any) {
      const status = error?.status ?? error?.response?.status;
      if (status !== 429 || attempt === maxRetries) throw error;

      const jitterMs = Math.floor(Math.random() * 300);
      const waitMs = 1000 * 2 ** attempt + jitterMs;
      await new Promise(resolve => setTimeout(resolve, waitMs));
    }
  }
  throw new Error("unreachable");
}
只对 429 做退避重试,不要对所有错误盲目重试。
用队列把并发限制到 2
typescript
async function runLimited<T>(tasks: (() => Promise<T>)[], concurrency = 2) {
  const results: T[] = [];
  let index = 0;

  async function worker() {
    while (index < tasks.length) {
      const current = index++;
      results[current] = await tasks[current]();
    }
  }

  await Promise.all(Array.from({ length: concurrency }, worker));
  return results;
}
批量任务先限并发,再加退避,通常能解决大部分 429。