限流重试、指数退避、随机抖动

调用大模型 API 时,429 限流重试指数退避是一套应对频率限制的自动恢复机制。下面分别解释。


1. 429 状态码:你被限流了

HTTP 429 Too Many Requests 表示你在短时间内发送了太多请求,超出了 API 的速率限制 (例如每分钟最多 60 次)。服务器会拒绝请求并返回这个状态码,通常还会附带 Retry-After 头,提示需要等多少秒后重试。

如果不处理 429,直接报错退出,你的任务就会中断。


2. 限流重试:遇到 429 别放弃,等一等再试

限流重试 就是当收到 429 时,不立即报错,而是暂停一段时间,然后重新发送刚才的请求。这样可以自动扛过 API 的流量限制,让任务平滑完成。

最简单的重试是固定间隔,比如每次等 1 秒。但固定间隔有两个问题:

  • 如果限流是持续的,每秒重试一次仍然可能反复触发 429,形成"踩踏";

  • 如果多个客户端同时被限流,又在同一时刻重试,会导致新的限流风暴。


3. 指数退避:让等待时间越来越长,越来越"聪明"

指数退避(Exponential Backoff) 是一种动态计算重试等待时间的策略:

  • 第一次重试:等待 1 秒

  • 第二次重试:等待 2 秒

  • 第三次重试:等待 4 秒

  • 第 n 次重试:等待 2^(n-1) 秒(常加上上限,如最大 64 秒)

等待时间指数级增长,给服务器足够的时间恢复,同时避免客户端在短时间内密集重试。

为什么要加"随机抖动"(Jitter)?

如果成千上万个请求同时被限流,它们都按相同的指数时间重试,又会在同一刻同时涌入服务器,再次造成拥塞。随机抖动就是在等待时间上加一个随机值(例如 ±10% 的浮动),把重试的时间点"打散"。

带抖动的指数退避公式(以 Python 为例):

复制代码
import random
import time

def exponential_backoff_with_jitter(retry_count, base=1, max_wait=64):
    wait = min(base * (2 ** retry_count), max_wait)
    jitter = wait * 0.1 * random.random()  # 增加最多 10% 的随机抖动
    return wait + jitter

整体流程示例

复制代码
请求 -> 返回 429 
   第 1 次重试:等 1.2 秒  -> 再请求 -> 还是 429
   第 2 次重试:等 2.5 秒  -> 再请求 -> 成功!

如果重试次数超过设定的最大值(如 5 次),则最终放弃并报错。


4. 在 LangChain 等框架中的应用

许多 LLM 框架已经内置了这种机制。例如 LangChain 中可以为模型设置 max_retriesrequest_timeout,底层使用了 tenacity 库实现指数退避重试。你只需配置参数,框架会自动处理 429 以及其它可重试的网络错误。

配置示例(以 ChatOpenAI 为例):

复制代码
from langchain.chat_models import ChatOpenAI

llm = ChatOpenAI(
    model="gpt-4",
    max_retries=5,            # 最多重试 5 次
    request_timeout=60,       # 单次请求超时
)

当你调用 llm.invoke(...) 时,若遇到 429,底层会自动进行指数退避重试,无需手写循环。


总结

概念 作用
429 限流 API 告诉你"太快了,暂停一下"
重试 自动等一等再试,而不是直接失败
指数退避 让等待时间越来越长,给服务器喘息空间
随机抖动 打散重试时刻,避免同时涌入

这套机制是调用大模型 API 时保证稳定性的基本功,几乎所有生产级代码都会采用"指数退避 + 随机抖动"的重试策略。

相关推荐
爱勇宝7 小时前
大多数人不是在使用 AI 赚钱,而是在帮 AI 公司赚钱
前端·后端·程序员
冬奇Lab8 小时前
每日一个开源项目(第143篇):page-agent - 纯 JS 的网页 GUI Agent,无需截图、无需插件、无需后端
前端·人工智能·agent
IT_陈寒13 小时前
React的这个渲染问题连官方文档都没说清楚
前端·人工智能·后端
追逐时光者14 小时前
别再满网找零散工具了,腾讯 QQ 浏览器这个“帮小忙”工具箱真能省时间
前端·后端
Asmewill16 小时前
grep&curl命令学习笔记
前端
stringwu16 小时前
Flutter 开发必备:MVI 架构的高效实现指南
前端·flutter
用户21366100357217 小时前
Vue2组件化开发与父子通信
前端·vue.js
Momo__18 小时前
TypeScript satisfies 操作符——比 as 更安全的类型守门员
前端·typescript
用户21366100357218 小时前
Vue2事件系统与指令进阶
前端·vue.js
labixiong18 小时前
实现一个能跑的迷你版Promise(一)
前端·javascript·面试