API 限流与重试策略:别再裸调大模型接口了
陈陈老师511 阅读
很多刚接大模型 API 的同学,代码里就是一行 fetch 或 client.chat.completions.create,没有重试、没有限流。线上并发一高,429 刷屏,用户体验直接崩。这篇讲讲生产级调用怎么设计。
先区分错误类型:
- 429(限流):请求太多,等一会儿重试通常能成功。OpenAI 的响应头里带 retry-after 字段,告诉你要等多久,优先用这个,别自己瞎猜。
- 5xx(服务端错误):模型服务暂时挂了,退避重试,但要限次数,别无限重试加重服务负担。
- 4xx(参数错误):重试也没用,直接抛给上层,记录日志。
重试实现(退避 + 抖动):
Python
import time, random
def call_with_retry(fn, max_retries=3):
for i in range(max_retries):
try:
return fn()
except RateLimitError as e:
wait = e.retry_after or (2 ** i) + random.uniform(0, 1)
time.sleep(wait)
except APIStatusError as e:
if e.status_code >= 500 and i < max_retries - 1:
time.sleep(2 ** i)
else:
raise
raise
指数退避 + 随机抖动,避免所有重试同时爆发(惊群效应)。
并发控制:
-
信号量限流。客户端用 asyncio.Semaphore 或 threading.Semaphore 控制并发数,别一股脑全发出去。
-
令牌桶。如果 API 有明确的 RPM(每分钟请求数)限制,用令牌桶平滑速率,别在 1 秒内把 60 次配额打光。
异步与队列: 实时场景用并发控制 + 重试;非实时场景(批量处理)丢进队列,worker 慢慢消费,天然削峰。
可观测性:
- 记录每次调用的:模型、token 数、耗时、错误类型
- 429/5xx 单独告警
- 成功率低于阈值自动降级(切备用模型/备用渠道)
坑:
-
别把重试写在循环里直接睡——异步代码里用 asyncio.sleep,阻塞代码用 time.sleep,用错了会卡死事件循环。
-
幂等性:有些调用(如生成任务)重试会重复执行,如果你的操作有副作用(比如扣费、写库),重试要保证幂等。
总结:重试 + 退避 + 并发控制 + 可观测性,是生产调用的基本盘。
评论0
还没有评论,来抢沙发~