限流与故障转移
按密钥设置的限制、容量排队和自动故障转移如何工作,它们返回哪些状态码,以及如何安全地重试。
请求到达模型之前要经过三道关卡:你为密钥设置的限制、为该模型提供服务的渠道容量,以及这些渠道的健康状况。大部分容量和健康问题由网关自己消化:短暂排队,或在另一个渠道上重试。真正到达你这里的,是一个短暂、可重试的 429 或 502。
为密钥设置的限制#
每个密钥都可以设置 每分钟请求数 限制和 最大并发请求数 限制。在 API 密钥页面创建或编辑密钥时,在 额度与限制 中设置。两者默认关闭。
| 限制 | 计算方式 |
|---|---|
| 每分钟请求数 | 最近 60 秒内(滚动窗口)开始的请求。 |
| 最大并发请求数 | 正在进行的请求,包括尚未结束的打开中的流。 |
触及限制的请求最多等待 2 秒以获得空位。如果仍没有空位,请求失败并返回 429,消息为 This API key has reached its rate or concurrency limit.,并带有以秒为单位的 retry-after 响应头。为不同工作负载使用各自带限制的独立密钥,可以避免一个工作负载挤占另一个。其他密钥设置请参阅 API 密钥。
容量排队#
每个渠道能同时服务的请求数是有限的。当请求要去的渠道已满时,网关会尝试为该模型提供服务的其他渠道。当它们全部已满时,请求会进入预计最先空出来的那个渠道的队列。
请求为等待容量总共最多等待 10 秒。如果被接纳,响应中会包含 x-lovely-queued-ms,标明它等待的时长。如果未被接纳,请求失败并返回 429,消息为 All upstream capacity for this model is busy. Retry shortly.,并带有 retry-after 响应头。
排队中的请求在实际运行之前不收费,被 429 拒绝的请求完全不收费。
自动故障转移#
当某个渠道失败时,网关会在同一渠道分组内的另一个渠道上重试请求,每个请求最多尝试三次。在以下情况下,网关会进行故障转移:
- 渠道超时、无法连接,或返回
408、409、425、429或任何5xx; - 渠道因自身原因而非你的原因拒绝请求;
- 渠道在流中第一个 token 之前失败(请参阅流式输出)。
新对话会分散到提供该模型的各个渠道。错误更多、或响应明显慢于其平时速度的渠道,在恢复之前分到的新对话会更少。持续失败的渠道会被暂时移出轮换,之后的请求会跳过它。锁定在该渠道上的对话会转到一个健康的渠道。
以下两种情况永远不会重试:
- 请求本身无效。 当模型以
400、404、413或422拒绝请求时,换到别处重试也会以同样的方式失败。你会收到该状态码及原因。 - 流已经开始。 第一个 token 之后,请求就固定在它的渠道上。之后的失败会以流中的错误事件呈现。
状态码#
| 状态码 | 原因 | 处理方式 |
|---|---|---|
429 | 触及密钥的 RPM 或并发限制。带有 retry-after。 | 等待 retry-after 秒,或提高密钥的限制。 |
429 | 该模型的全部容量连续 10 秒处于繁忙状态。带有 retry-after。 | 等待 retry-after 秒后重试。 |
429 | 尝试过的每个渠道都报告了速率限制。消息为 Upstream capacity for this model is busy. Retry shortly. | 使用退避策略重试。 |
502 | 尝试过的每个渠道都失败了。消息为 The model provider returned an error. Please retry. | 使用退避策略重试。 |
500 | 网关意外错误。 | 重试一两次,然后附上 x-lovely-request-id 联系支持。 |
402 | 余额小于或等于零,或密钥已达到消费上限。 | 充值或提高上限。不要重试。 |
400、404、413、422 | 请求无效、过大,或模型 ID 未知。 | 修正请求。不要重试。 |
401、403 | 密钥缺失、已吊销或已过期,或无权使用该模型。 | 修正密钥。不要重试。 |
错误类型遵循你的 API 格式:429 对应 rate_limit_error(Anthropic)、rate_limit_exceeded(OpenAI)或 RESOURCE_EXHAUSTED(Gemini),502 对应 api_error(Gemini 中为 UNAVAILABLE)。完整列表请参阅错误。
在客户端中重试#
网关已经在多个渠道之间重试过,所以收到 429 或 502 说明问题在多次尝试中一直存在。请使用指数退避加随机抖动再重试几次,并在存在 retry-after 时遵循它。
Anthropic 和 OpenAI SDK 默认就会这样做,对 408、409、429 和 5xx 重试两次。对于批处理任务,请提高重试次数上限:
import os
from openai import OpenAI
client = OpenAI(base_url="https://lovelyrouter.com/v1", api_key=os.environ["LOVELY_API_KEY"], max_retries=5)使用普通 HTTP 时,请实现同样的策略:
# --retry covers 429 and 5xx and honors retry-after
curl --retry 5 --retry-max-time 120 https://lovelyrouter.com/v1/chat/completions \
-H "Authorization: Bearer $LOVELY_API_KEY" \
-H "content-type: application/json" \
-d '{"model": "gpt-6.1-sol", "messages": [{"role": "user", "content": "Hi"}]}'对于流,只在错误出现在任何内容之前时才重试。如果流中途断开,你已经为部分输出付费;请决定是保留它,还是重新请求完整的回答。
余额与消费上限#
每个请求在运行前都会检查你的余额和密钥的消费上限。当余额小于或等于零,或密钥已用完其上限时,请求失败并返回 402:Insufficient balance. Top up at the dashboard. 或 This API key has reached its spend limit.。错误类型在 OpenAI 格式中为 insufficient_quota,在 Anthropic 格式中为 billing_error,在 Gemini 格式中为 RESOURCE_EXHAUSTED。
检查发生在请求开始时,扣费在请求结束几秒后结算。以正余额开始的请求总会运行到完成,因此余额最终可能略低于零;下一次充值会补上这部分。请参阅额度与计费。