把Claude API接入生产环境,跟本地跑个Demo完全是两回事。本地测试的时候,网络稳定、调用量小,基本不会出问题。一旦上线,用户量上来,各种报错就跟着来了:429限流、529服务过载、请求超时、连接中断,每一个都可能让功能直接不可用。
这篇文章不聊理论,直接讲生产环境里怎么处理这些错误、怎么设计重试逻辑。核心原则就一条:区分哪些错误值得重试,哪些错误重试也没用,然后给值得重试的错误配上正确的退避策略。
先搞清楚:Claude API的错误分几类
Anthropic官方文档把错误响应分成了几个大类,每一类对应的处理方式完全不同。
客户端错误(400、401、403、404、413):这些错误重试是没用的。400通常是请求格式有问题,比如JSON格式错误、缺少必填参数、messages数组为空;401是API Key无效或缺失;403是Key没有访问某个模型的权限;404是模型ID拼写错误或使用了已弃用的模型;413是请求体超过大小限制。这类错误必须改请求本身或改配置,重试只会浪费时间和配额。
限流错误(429):这是生产环境最常见的错误。Anthropic从三个维度限流:RPM(每分钟请求数)、ITPM(每分钟输入token数)、OTPM(每分钟输出token数),任何一个超了都会触发429。429是值得重试的,但重试策略有讲究,下面详细说。
服务端错误(500、529):500是Anthropic内部故障,529是服务过载。这两个都值得重试,但529还有一个特殊处理——可以配置备用供应商做故障转移。
网络错误和超时:这类错误通常表现为连接中断、读取超时,没有HTTP状态码。这类错误也值得重试,但需要注意超时配置。
生产环境重试策略:指数退避加抖动
为什么不能用固定间隔重试
如果多个客户端同时收到429,然后都等固定时间(比如3秒)再重试,它们会在同一时刻再次发起请求,造成新一轮的流量尖峰。这个现象叫“重试风暴”,用一句话概括就是:重试本身把限流问题维持住了。
解决办法是在退避时间上加入随机性,也就是“抖动”(jitter)。两种常用的抖动策略:
Full Jitter:退避时间 = random(0, min(cap, base * 2^attempt))。每次重试在0到指数增长的上限之间随机取值。实现简单,效果不错,适合大多数场景。
Decorrelated Jitter:退避时间 = min(cap, random(base, previous_sleep * 3))。每次的等待时间依赖于上一次的实际等待时间,在高并发场景下分散效果更好。
对于大多数Claude API的集成场景,Full Jitter就够了。只有当你同时有50个以上的并发调用共享同一个API Key时,才需要考虑Decorrelated Jitter。
Python实现:带抖动的重试装饰器
下面是一个生产环境可用的Python重试实现,覆盖了429和500系列错误:
import anthropic
import time
import random
from typing import Callable, TypeVar
T = TypeVar("T")
client = anthropic.Anthropic()
def with_retry(
fn: Callable[[], T],
max_retries: int = 3,
base_delay: float = 1.0,
) -> T:
"""带指数退避和抖动的重试逻辑"""
for attempt in range(max_retries + 1):
try:
return fn()
except anthropic.RateLimitError:
# 429限流:必须重试,加上抖动
if attempt == max_retries:
raise
delay = base_delay * (2 ** attempt) + random.uniform(0, 1)
print(f"触发限流,{delay:.1f}秒后重试 (第{attempt + 1}次)")
time.sleep(delay)
except anthropic.InternalServerError:
# 5xx服务端错误:重试,不需要抖动
if attempt == max_retries:
raise
time.sleep(base_delay * (2 ** attempt))
except (anthropic.AuthenticationError, anthropic.BadRequestError):
# 401、400等错误:重试没用,直接抛出
raise
这段代码里有个关键设计:抖动只加在429重试上,不加在500系列错误上。原因很简单——429是在竞争同一个token桶,多个客户端需要分散开;而500是服务端自己的问题,重试的客户端之间不存在竞争关系。
TypeScript实现:利用SDK内置重试
TypeScript SDK内置了重试机制,一行配置就能启用:
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({ maxRetries: 3 });
如果需要自定义逻辑,可以手动实现:
async function withRetry<T>(
fn: () => Promise<T>,
maxRetries = 3,
): Promise<T> {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
if (error instanceof Anthropic.RateLimitError && attempt < maxRetries) {
const delay = Math.pow(2, attempt) * 1000 + Math.random() * 1000;
await new Promise((resolve) => setTimeout(resolve, delay));
continue;
}
throw error;
}
}
throw new Error("重试次数已耗尽");
}
429限流:别只看RPM
很多人遇到429的第一反应是“我又没调几次,怎么就限流了”。问题在于,Claude的限流不只看请求次数。
Anthropic同时检查三个维度:RPM(每分钟请求数)、ITPM(每分钟输入token数)、OTPM(每分钟输出token数)。一个带长上下文的请求,比如你往Claude塞了10万token的代码让它review,一个请求就可能把ITPM配额打满。
排查步骤:
- 先看429错误响应里的
message字段,它会告诉你超的是RPM、ITPM还是OTPM - 到Anthropic Console查看当前Tier和剩余配额
- 如果是ITPM超限,压缩prompt长度或分批发送
- 如果是RPM超限,加请求间隔或做队列排队
Tier等级决定配额。Anthropic根据充值金额划分Tier,每升一级配额翻几倍。免费账户配额很低,充$5以上到Tier 1,$40以上到Tier 2,$200以上到Tier 3,$400以上到Tier 4。生产环境建议至少到Tier 2。
529服务过载:跟429不是一回事
529跟429看起来都是“服务不可用”,但成因完全不同。429是你自己的请求超限了,529是Anthropic自己的容量饱和了。
对于529的处理,除了指数退避重试,还有一个更重要的策略:故障转移。Anthropic的模型在AWS Bedrock和Google Vertex上也能调用。当直接API返回529时,可以把请求路由到Bedrock或Vertex上的Claude。
这就是“网关模式”的价值——在所有Claude调用前面放一个薄薄的内部服务,集中处理重试逻辑、日志、Key轮换、成本追踪和限流。
超时配置:区分连接超时和读取超时
生产环境的超时配置不能一刀切。需要区分两种情况:
连接超时:建立TCP连接和TLS握手的时间。通常3-10秒够用,网络好的环境5秒,差的环境10秒。
读取超时:从发出请求到收到完整响应的时间。普通请求30-60秒,流式请求不要设读取超时,或者设成很大的值(300秒以上)——因为流式输出是持续接收数据,不是等待单次响应。
# 非流式请求的超时配置
sync_client = anthropic.Anthropic(
timeout=anthropic.Timeout(
connect=5.0,
read=60.0,
write=10.0,
),
)
# 流式请求的超时配置
stream_client = anthropic.Anthropic(
timeout=anthropic.Timeout(
connect=5.0,
read=300.0, # 流式输出可能持续几分钟
write=10.0,
),
)
长请求的一个坑:有些网络会在空闲一段时间后断开连接,导致请求失败或超时。对于超过10分钟的请求,建议使用流式API或Message Batches API。
生产环境部署的检查清单
上线之前,对照这份清单过一遍:
错误分类处理
- 400、401、403、404、413:不重试,记录日志并告警
- 429:指数退避+抖动重试
- 500、529:指数退避重试,529可配置故障转移
- 网络超时:有限重试
重试配置
- 最大重试次数不超过3次(避免无限重试消耗配额)
- 使用指数退避,base delay从1秒开始
- 429重试必须加抖动,避免重试风暴
- 使用
Retry-After响应头(如果有)来确定等待时间
可观测性
- 记录
request_id,排查问题时提供给Anthropic支持 - 日志包含:HTTP状态码、错误码、错误消息、request_id、延迟、重试次数、trace_id
- 监控错误率、延迟、token使用量、余额
降级方案
- 核心业务准备备用模型或备用供应商
- 529持续时切换至Bedrock或Vertex
Claude API的错误处理,核心就一句话:区分可重试错误和不可重试错误,给可重试错误配上正确的退避策略。 429和5xx值得重试,但必须有抖动;400和401重试是浪费时间。把重试逻辑、超时配置、日志监控这三件事做到位,生产环境的稳定性就有了基本保障。
相关内容
