> ## Content Index
> Fetch the complete content index at: https://orbiorbi.com/news/llms.txt
> Use this file to discover other available public pages before exploring further.

# AI API 429 错误怎么解决？RPM、TPM 限流与重试排查指南
- URL: https://orbiorbi.com/news/ai-api-429-paizhang/
- Published: 2026-10-15T16:22:56.000Z
- Updated: 2026-10-15T16:22:56.000Z
- Description: 面向正在接入和排查 AI API 的开发者：先找出 429 的触发原因，再用队列、限流和有边界的重试恢复调用。
- Author: Orbis News
- Tags: API 接入与排障

测试时 API 一切正常，上线后却频繁出现 `429 Too Many Requests`：这种情况不一定是用户突然变多了。长提示词可能耗尽 Token 限额，多个服务可能共享同一份容量，自动重试也可能把一次短暂拥堵变成持续报错。

**遇到 429，先读取错误正文，确认限制来自哪里，再决定降低请求速率、减少 Token，还是处理配额问题。** 本文解释 RPM、TPM 与并发的区别，梳理常见原因，并给出带指数退避、随机抖动和 `Retry-After` 处理的 Python 示例。

## 429 报错快速排查：先检查这六项

1. **保留状态码和错误详情。** 记录时间、模型、请求 ID、错误类型及响应头。排查时使用脱敏日志，不记录 API Key。
2. **判断是否属于临时限流。** 如果正文明确提示余额、计费或配额不足，持续重试通常没有帮助，应先处理对应问题。
3. **确认限流范围。** 查清限制按账号、项目、模型、API Key、IP，还是上游服务共享计算。
4. **同时检查 RPM 和 TPM。** 请求少也可能因为单次输入或输出太长而触发限制。
5. **检查突发流量和重试叠加。** 多个 Worker 同时启动、定时任务集中执行、SDK 与业务层重复重试，都可能放大流量。
6. **按照服务端提示等待。** 如果有有效的 `Retry-After`，至少等待指定时间；没有时再采用有上限的指数退避与随机抖动。仍持续触发限制时，调整队列、用量或容量。

HTTP 429 的含义和限制范围可以参考 [MDN 的 429 说明](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/429?ref=orbiorbi.com)。具体原因仍应结合当前服务返回的错误正文判断。

## 为什么大模型 API 需要多种限流指标？

请求次数不能完整反映大模型任务的计算需求。

一次短文本分类可能只输入 200 个 Token，返回一个标签；一次代码库分析可能输入数千个 Token，再生成长篇回答。两者都算一次请求，但消耗的 Token、处理时间和计算资源差别很大。

不同限制分别应对不同的流量特征：

- **短而频繁的请求**更容易耗尽请求次数额度。
- **长提示词和大上下文**可能在请求不多时耗尽 Token 额度。
- **较长的输出**增加 Token 消耗，也让请求保持更长的执行时间。
- **集中到达的流量**可能在平均用量正常时触发短时限制。
- **通过实时接口执行大量离线任务**会占用在线容量，即使任务并不需要立即返回。

常见指标包括 RPM、TPM，以及按小时、按天统计的请求或 Token 限额。图片服务还可能使用 IPM、IPD，分别表示每分钟、每天的图像数量。**只要其中一项适用限制达到上限，请求就可能被限制。** 并非每个平台都会使用全部指标。

## RPM 和 TPM 有什么区别？

RPM 和 TPM 衡量的是不同维度。

| 指标  | 含义          | 常见瓶颈          |
| --- | ----------- | ------------- |
| RPM | 每分钟请求数      | 高频小请求         |
| TPM | 每分钟 Token 数 | 长提示词、大上下文、长输出 |
| RPH | 每小时请求数      | 小时级使用上限       |
| RPD | 每天请求数       | 每日请求额度        |
| TPD | 每天 Token 数  | 每日 Token 消耗   |

### RPM 限制什么？

RPM 限制的是一定范围内每分钟可发送的请求次数。这里的范围可能是账号、项目、模型或其他资源，取决于服务规则。

即使每次请求都很短，也可能触发 RPM 限制。自动补全、聊天程序、Agent 循环，以及把一次用户操作拆成多次模型调用的工作流，都容易遇到这种情况。

例如，一个 Agent 任务分别调用模型完成规划、工具选择、结果验证和最终回答。用户只提交了一次任务，后台却发出了四次或更多请求。

### TPM 限制什么？

TPM 限制的是每分钟计入限流的 Token 数量。系统提示词、历史对话、检索文档、代码、推理内容和长输出，都可能增加消耗。

排查时记录实际返回的 `prompt_tokens`、`completion_tokens`、`total_tokens`，或当前协议中的对应字段。**用于限流的计算口径不一定与最终账单完全相同**：有些服务会参考预估输入量、输出上限等信息，具体以服务文档为准。

假设两个应用每分钟都发送 10 次请求：

- 应用 A 每次使用 300 个总 Token，约为 3,000 TPM。
- 应用 B 每次使用 8,000 个总 Token，约为 80,000 TPM。

两者都是 10 RPM，但应用 B 更容易先达到 TPM 上限。

### 限流按账号、模型还是 API Key 计算？

接入前要确认限制的作用范围。部分服务按账号或项目共享容量，部分会按模型、模型组、Key 或其他维度进一步限制。

**多创建几个 API Key，不等于一定获得更多容量。** 如果这些 Key 共享同一账号、项目或上游限额，总容量可能完全不变。

同样，不要默认不同模型拥有独立额度，也不要默认套餐升级会同时增加所有指标。部署前核对目标模型、当前账号等级和实际限额。

## 为什么请求不多，还是收到 429？

429 通常提示请求触及适用的使用限制，但只看状态码，无法确定究竟是哪种限制。应继续查看错误代码、正文和响应头。

### 请求次数过多

集中发送的短请求可能超过 RPM。Agent 一次用户操作触发多次调用，会让前台看到的任务数远低于实际请求数。

### Token 消耗过高

少量长请求也可能超过 TPM。常见原因包括重复发送系统提示词、携带完整历史记录、返回过多检索内容、输入长代码文件，以及设置不必要的输出上限。

### 多个服务共享同一限额

多个应用、后端服务、Worker 或 Key 可能共享账号、项目、模型或上游容量。单独观察每个服务时流量不大，加总后却已经达到上限。

### 流量集中到达

每小时或每天平均用量不高，不代表某一分钟内没有突发。定时任务同时启动、队列一次释放大量任务，都会造成短时峰值。

因此，排查 429 应同时查看队列积压、请求释放速率和分钟级用量，而不是只看全天总量。

### 自动重试放大了负载

立即重试会向已经受限的系统继续发送请求。多个 Worker 同时失败、同时重试，可能产生重试风暴，让问题持续更久。

### 模型还有小时级或每日限制

部分模型或套餐还设置小时级、每日请求数或 Token 上限。RPM 和 TPM 没有达到上限，也不代表其他配额仍有剩余。

### 专属部署的接入配置不匹配

使用专属部署时，还要确认目标地址、部署名、模型 ID 和 Key 权限是否匹配。请求误入共享接口时，可能触发另一套限流规则。

专属容量是否免除某些共享限制、还受哪些网关或实例限制，取决于部署方案。不要将“专属”理解为无限吞吐。

如果错误明确指向余额、账单、权限或已耗尽的长期配额，应先处理这些条件，再重试。没有足够错误信息时，向服务方提供请求 ID、时间和脱敏错误详情。

## 429、503、504 有什么区别？

不是所有临时 API 故障都属于限流。先区分状态码，再阅读具体错误详情。

| 状态码 | 常见含义                             | 首先怎么处理                           |
| --- | -------------------------------- | -------------------------------- |
| 429 | 请求速率、Token 或其他使用限制；部分服务也用它报告配额问题 | 确认限制类型；临时限流降低速率并退避，配额问题先处理配额     |
| 503 | 服务暂时不可用，可能涉及负载或维护                | 检查服务状态，仅对适合重试的任务做有限重试或使用已验证的备用方案 |
| 504 | 网关未及时收到上游响应                      | 检查任务状态、耗时和超时设置，避免重复提交已在执行的任务     |
| 400 | 请求格式或参数不符合要求                     | 按错误正文修改请求；模型 ID 错误也可能返回其他状态码     |
| 401 | 身份认证失败或凭据缺失                      | 检查 Key、认证头和目标服务是否匹配              |
| 403 | 没有相应权限                           | 检查账号、项目和模型访问权限                   |
| 404 | 接口路径、模型或目标资源不存在                  | 检查 Base URL、路径拼接、接口协议和资源 ID      |

长时间的非流式请求如果反复出现 504，原样重试未必有效。对于支持流式的场景，可评估流式返回、减少输出长度，或调整客户端与网关超时。

流式响应有助于持续传输数据，**不能增加 RPM、TPM，也不能解决所有上游计算超时**。对于异步任务，应先查询任务状态，再决定是否重新提交。

## 怎样正确处理限流和重试？

只对适合重试的临时故障进行重试，并限制次数、等待时间和整体业务耗时。先确认任务是否允许重复执行，再选择策略。

### 使用指数退避

连续失败后逐步增加等待时间，例如约 1 秒、2 秒、4 秒、8 秒，同时设置等待上限和尝试次数上限。具体等待策略可参考 [AWS 对指数退避和随机抖动的说明](https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/?ref=orbiorbi.com)。

### 加入随机抖动

在退避时间上增加随机偏移，避免多个客户端在相同时间再次发起请求。否则，一起失败的请求可能再次一起到达。

### 用队列控制请求释放速率

队列可以吸收短时突发，再按可承受速率释放任务。交互请求可优先处理，后台任务等待可用容量。

令牌桶、漏桶等机制控制新请求何时发出；并发上限控制同时执行多少请求。两者解决的问题不同，通常需要配合使用。

### 设置最大尝试次数

某些场景可以从最多 3—5 次总尝试开始，再结合延迟要求和业务成本调整。“尝试 5 次”包含首次请求，不是首次之外再重试 5 次。

最后一次仍失败时，返回明确错误、保留任务等待后续处理，或进入经过验证的备用方案。交互任务还应设置整体截止时间，避免用户离开后仍持续执行。

### 避免重复执行外部操作

Agent 可能调用付款系统、数据库、文件操作等外部工具。重试模型请求，不应自动重复已经成功的业务操作。

使用幂等键、操作 ID、任务状态和去重机制保护下游。网络超时也不等于服务端没有执行；重新发起生成可能造成额外费用。

### 只保留一层重试，并处理 Retry-After

SDK 和业务层如果都在重试，总尝试次数可能相乘。使用应用层策略时，应关闭 SDK 重试，或把两层行为一起纳入预算。相关原则可参考 [OpenAI 官方限流处理文档](https://developers.openai.com/api/docs/guides/rate-limits?ref=orbiorbi.com#retrying-with-exponential-backoff)。

`Retry-After` 可以表示等待秒数，也可以表示一个 HTTP 日期。服务端提供有效提示时，至少等待指定时间；如果超出当前任务能接受的等待预算，应停止并延后任务，不能擅自缩短等待后继续发送。字段格式见 [MDN 的 Retry-After 说明](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Retry-After?ref=orbiorbi.com)。

下面的 Python 示例用于 **OpenAI 兼容的 Chat Completions 接口**。它关闭 SDK 重试，限制总尝试次数与累计重试等待，并对已识别的配额或计费错误直接退出。

运行前安装 `openai`，设置 `API_KEY`、`API_BASE_URL` 和 `MODEL_ID`。使用服务文档给出的完整 Base URL；按实际模型要求调整 `max_tokens` 等参数。示例使用 Python 3.10 或更高版本。

```python
import math
import os
import random
import time
from datetime import datetime, timezone
from email.utils import parsedate_to_datetime

from openai import APIConnectionError, APIStatusError, OpenAI

client = OpenAI(
    api_key=os.environ["API_KEY"],
    base_url=os.environ["API_BASE_URL"],
    max_retries=0,
    timeout=30.0,
)

# Extend this set with the documented error codes of your API provider.
NON_RETRYABLE_CODES = {
    "insufficient_quota",
    "billing_hard_limit_reached",
    "billing_not_active",
}

def parse_retry_after(value: str | None) -> float | None:
    if not value:
        return None
    try:
        seconds = float(value)
        return max(0.0, seconds) if math.isfinite(seconds) else None
    except ValueError:
        pass
    try:
        retry_time = parsedate_to_datetime(value)
        if retry_time.tzinfo is None:
            retry_time = retry_time.replace(tzinfo=timezone.utc)
        seconds = (retry_time - datetime.now(timezone.utc)).total_seconds()
        return max(0.0, seconds)
    except (TypeError, ValueError, OverflowError):
        return None

def create_chat_completion(
    messages: list[dict[str, str]],
    max_attempts: int = 5,
    max_retry_wait: float = 60.0,
):
    if max_attempts < 1 or max_retry_wait < 0:
        raise ValueError("Invalid retry limits")

    waited = 0.0
    for attempt in range(max_attempts):
        try:
            return client.chat.completions.create(
                model=os.environ["MODEL_ID"],
                messages=messages,
                max_tokens=800,
            )
        except APIStatusError as error:
            if (
                error.status_code not in {429, 503, 504}
                or error.code in NON_RETRYABLE_CODES
                or attempt == max_attempts - 1
            ):
                raise
            backoff = min(30.0, 2.0 ** attempt)
            server_delay = parse_retry_after(
                error.response.headers.get("retry-after")
            )
            delay = server_delay if server_delay is not None else backoff
            delay += random.uniform(0.0, min(1.0, delay * 0.25))
            if waited + delay > max_retry_wait:
                raise
        except APIConnectionError:
            if attempt == max_attempts - 1:
                raise
            delay = min(30.0, 2.0 ** attempt) + random.uniform(0.0, 1.0)
            if waited + delay > max_retry_wait:
                raise

        time.sleep(delay)
        waited += delay

    raise RuntimeError("The request failed after all retry attempts.")

```

`max_attempts=5` 表示最多发起五次尝试；`max_retry_wait=60` 只限制累计休眠等待，不包含网络调用耗时。`timeout=30.0` 也不等于整个业务只能运行 30 秒；完整的截止时间与取消机制应由上层应用控制。

服务方的错误代码可能不同，应按照实际文档补充 `NON_RETRYABLE_CODES`。示例不适合直接重放已经输出部分内容的流，也不会替你判断异步任务或外部操作是否已经成功。

## 如何估算 API 的初始并发上限？

RPM、TPM 衡量吞吐量，并发衡量同时执行的请求数量，不能互相直接替代。

在限额以总 Token 为统计口径的假设下，可以用观测数据粗估起点：

```text
RPM 允许的请求速率 = RPM ÷ 60
TPM 允许的请求速率 = TPM ÷ 每次请求的观测总 Token 数 ÷ 60
计划释放速率 = min(RPM 速率, TPM 速率) × 安全系数
并发规模参考值 = 计划释放速率 × 请求耗时

```

假设一个模型的限制和观测值为：

- 1,200 RPM；
- 60,000 TPM；
- 每次请求约 1,200 个总 Token；
- P95 请求耗时约 4 秒；
- 安全系数为 80%。

按 RPM 计算：

```text
1,200 ÷ 60 = 20 次/秒

```

按 TPM 计算：

```text
60,000 ÷ 1,200 ÷ 60 ≈ 0.83 次/秒

```

这里 TPM 是更紧的约束。应用安全系数后：

```text
0.83 × 0.8 ≈ 0.67 次/秒

```

再用 P95 耗时估算并发规模：

```text
0.67 × 4 ≈ 2.68 个同时执行的请求

```

可以从并发 2 或 3 开始观测，同时将请求释放速率控制在约 0.67 次/秒以内。这是一组演示数据，不代表任何平台的实际限额。

该公式只是容量规划的起点。平均 Token 不能覆盖长请求尾部风险；用 P95 耗时相乘是规划参考，也不是严格的并发保证。请求长度、延迟、服务端窗口及其他限制都会影响结果。

**只设置并发上限，不能自动遵守 RPM 或 TPM。** 快请求完成后立刻补入新请求，仍可能超出分钟限额。因此还需要请求节流，以及按服务端口径进行 Token 用量控制。

## 应用架构怎样适应 API 限流？

限流处理应进入日常流量设计，而不是等上线报错后再补一个重试循环。

### 统计一次用户操作会触发多少次请求

一个界面动作可能包含规划、检索、工具调用和结果验证等多次模型请求。容量估算应以实际调用次数为基础。

### 观察 Token 消耗的分布

记录输入、输出和总 Token 的中位数、P95 与最大值。平均值正常时，少量超长请求仍可能造成问题。

### 根据实际限流范围分配队列

模型拥有独立额度时，可以按模型划分队列和并发限制；多个模型共享账号或上游额度时，还需要共同的总量限制。单一全局限制和完全独立的队列，都可能与真实规则不匹配。

### 限制提示词和输出规模

去掉重复上下文，限制检索结果数量，总结较早的对话，并设置合理的输出上限。这些措施通常能同时降低 Token 压力和调用成本。

### 按任务要求选择模型

分类、抽取、推理、编程和多模态任务，可以根据质量、延迟、成本与可用容量选择合适的模型。

备用模型必须验证任务效果与接口兼容性。切换模型不应被当成绕过平台限制的方法，也不能保证另一个模型拥有独立容量。

### 将适合的离线任务移到批处理

评测、文档处理、分类和大规模抽取不一定需要实时结果。如果服务提供批处理 API，可评估其支持的模型、接口、处理时限、费用和独立限额。

如果没有批处理 API，也可以使用自有任务队列按允许速率执行；普通循环请求不会因此自动获得批处理折扣或额外容量。

### 持续接近上限时申请扩容

提示词优化、队列和有限重试可以缓解短时峰值，但不能解决长期需求超过容量的问题。

当正常业务持续接近限额时，按服务方的流程申请更高 RPM、TPM 或其他容量。准备预计请求量、输入输出分布、峰值、任务类型和延迟要求，帮助判断需要增加的是哪一项资源。申请本身不等于一定获批。

### 评估专属容量

持续高吞吐或需要更可预测容量的应用，可以评估服务方提供的专属部署方案。比较实际吞吐、延迟、排队时间、成本，以及仍然适用的网关和实例限制，不要默认专属部署没有上限。

## AI API 限流常见问题

### TPM 是什么意思？

TPM 是每分钟 Token 数，用于限制单位时间的 Token 使用。长提示词、对话历史、检索文档、推理内容和长输出，都可能让应用先达到 TPM，而不是 RPM。

### 为什么请求很少也会报 429？

少量长请求可能消耗大量 Token；突发流量、共享容量、重试叠加、小时或每日限制，也可能触发 429。先阅读错误正文，不要只看前台用户数。

### 所有 API 请求失败都应该重试吗？

不应该。适合重试的临时限流、部分 503、504 或连接错误，可以采用有限退避。参数错误、认证失败、权限不足、路径错误，以及需要处理账单或长期配额的问题，应先修正原因。超时后的任务还需要判断是否已经执行。

### 提高 RPM 会同时提高 TPM 吗？

不一定。它们是不同的约束，可能随模型、账号、项目或部署方案变化。申请扩容时应分别确认。

### 怎样减少 API 限流错误？

控制请求释放速率，管理并发与 Token 用量，使用队列和带随机抖动的有限重试；缩短不必要的上下文，将适合的离线任务移出实时调用。当持续需求超过容量时，再申请扩容或评估其他部署方案。

准备继续接入时，可从 [API 平台](https://api.tmlab.store/?ref=orbiorbi.com)进入，按当前接入文档核对 Base URL、模型 ID 和凭据，再用一条最小请求验证配置。排障求助时附上请求时间、请求 ID 和脱敏错误正文，更容易定位问题。

延伸阅读：[模型选型专题](https://orbiorbi.com/news/tag/topic-pick/)。