收益:
- 可以解释速度限制 (RPM/ITPM/OTPM) 和 429 错误
- 使用 retry-after 实现指数退避和重试
- 正确分类处理常见HTTP错误码(400/401/429/500/529)
在生产环境中,没有任何 API 能够始终完美响应。有时您发送请求的速度太快而达到了限制;有时服务器暂时繁忙;有时你的要求从一开始就是错误的。可靠的集成与业余尝试的区别在于,它能够预测性地、自动地处理这些情况。在本单元中,您将了解速率限制 (RPM/ITPM/OTPM)、429 错误、指数退避重试以及常见 HTTP 错误代码的正确分类。目标:构建一个强大到用户永远不会注意到的流程。
什么是速度限制?
提供商限制交换机在给定时间段内可以完成的工作量。这种保护;它可以保护基础设施和您免受突然的成本爆炸的影响。常见的限制类型有以下三种:
- RPM(每分钟请求数):每分钟请求数。
- ITPM(每分钟输入令牌数):每分钟可以处理的输入令牌。
- OTPM(Output Tokens Per Minute):每分钟可以产生的输出代币。
如果超出任何这些限制,提供商将拒绝请求并返回 429 错误代码。限制通常根据您的帐户级别(等级)而有所不同,并且可能会随着时间的推移而增加。
提示:您可以通过响应标头观察何时接近限制。大多数提供商都会使用 x-ratelimit-remaining-* 等标头报告您的剩余配额。监控这些值并限制前面的流量是防止出现 429 问题的最成熟方法。
正常 双线429服 [双线429服]
429(速率限制)是一个临时且可重试的错误。正确的响应是等待请求一段时间,然后重试。但持续的等待是不够的;如果所有人同时再次尝试,则会再次达到限制。解决方案是指数退避:每次失败的尝试都会以指数方式增加等待时间。
# 指数退避逻辑 试验 1 → 429 → 等待 1 秒 试验 2 → 429 → 等待 2 秒 试验 3 → 429 → 等待 4 秒 试验 4 → 429 → 等待 8 秒(+ 小随机“抖动”)... 最多 N 次试验后放弃并报告
添加一点随机性(抖动)可以防止请求在尝试同时重试时发生冲突。此外,429 响应通常带有“retry-after”标头:“在这么多秒内重试”。尊重这个称号,比盲目等待更准确。
注意:当你收到 429 时,“通过发送更多请求来强制它”会使情况变得更糟;限制继续被填满,并且没有请求通过。正确的反应是后退,而不是加速。好消息:大多数官方 SDK 都会自动重试 429 和服务器错误并进行回退 - 在手动安装之前使用 SDK 的这种行为。
HTTP 错误代码分类
并非每个错误都是相同的。关键区别:可以重试还是请求/身份问题?
代码
含义
可以再试一次吗?
正确反应
400
无效请求(格式/参数错误)
不
更正请求;不要再次发送相同的内容
401
身份验证错误(密钥无效/丢失)
不
修复键/标题
403
没有授权(无法访问模型/功能)
不
检查权限/范围
404
未找到(模型 ID/端点不正确)
不
正确的型号 ID/地址
第429章
超过速度限制
是的
撤退+之后重试
500
服务器错误
是的
再尝试撤退
第529章
服务器超载
是的
再尝试撤退
黄金法则:429、500、529是临时的;再次尝试退出。 400、401、403、404是请求/身份问题;再尝试也解决不了问题,而且还白费力气。您的代码必须区分这两组。
循序渐进:持久的通话
- 提交请求。如果成功,则继续。
- 对错误代码进行分类。可以再试一次吗?
- 如果可尝试:遵循重试后,应用指数退避 + 抖动,尝试有限次数(例如最多 5 次)。
- 如果没有尝试过:修复(格式/密钥)并停止;不要在循环中重复相同的错误请求。
- 考虑放弃。如果在n次尝试后仍然不成功,则向用户显示礼貌消息并记录该事件(跟踪单元11)。
# 鲁棒调用 伪codedene = 0repeat: response = request_at() if response.success: 返回响应 if response.code in [429, 500, 529] and try < 5: wait = retry_after ?? (2^尝试秒+抖动)睡眠(等待);尝试+= 1;再次 git if response.code in [400, 401, 403, 404]: save_error(response); return "请求必须修复" return "永久错误,稍后再试"
# 向用户礼貌地反馈(当重试次数用尽时)“我现在很忙,无法处理您的请求。请稍后重试,或者我已保存您的请求,准备好后我会回复您。”
弱提示/强提示(这里:错误信息设计)
# 弱(向用户显示原始错误)“错误 429:rate_limit_error”
# STRONG(用户友好、令人放心、建议采取行动)“系统出现暂时拥塞。我们已安全收到您的请求,正在自动重试。如果几秒钟内没有出现结果,您可以刷新页面。”
向最终用户透露原始技术错误既会破坏信任,也可能成为安全漏洞。在内部对错误进行分类,并向用户提供冷静、以行动为导向的消息;只需写下技术细节以供记录。
三个迷你箱
案例一——交通爆炸导致船只失事。活动当天,客户服务机器人收到了 429 的流量激增;代码中没有重试,每个错误都作为“错误”直接反映给用户。他们添加了指数回撤+重试后;对于相同的流量,请求通过延迟几秒钟,用户没有看到任何错误。
案例 2 — 在循环中尝试 400。由于模型 ID 无效,集成收到 404 错误,但将所有错误视为“暂时的”错误并在无限循环中重试;原木膨胀并产生不必要的负载。他们添加了错误分类:404 被认为是永久性的,循环被停止,模型 ID 被更正。教训:不要再犯每一个错误。
案例 3 — 从正面管理限制。数据丰富作业持续在 429 限制下运行。他们遵循 x-ratelimit-remaining 标头并根据配额限制流量。因此,他们保持着稳定的速度,略低于极限,没有跑出任何 429 秒;这项工作的完成更加可预测且更快。
常见错误
- 429 增加速度:使情况变得更糟;转而撤退。
- 重试每个错误:400/401/404 是永久性的;再尝试就是一种浪费。
- 使用固定等待:造成冲突;使用指数+抖动。
- 忽略“retry-after”:遵守提供商指定的时间是最准确的。
- 向用户揭示原始错误:动摇信任,产生漏洞;里面分类一下。
- 无限次重试:设置上限(例如重试5次);然后优雅地放弃。
更深入:队列、并发和断路器
忍受单一的欲望是第一步;真正的成熟是在不达到限制的情况下管理大量请求。三个概念在这里发挥作用。
队列:您将请求放入队列中,以受控的速度发送它们,而不是立即发送。队列可以平滑突发的流量:即使同时有 1,000 个请求到达,队列也会以低于限制的速率释放它们。这样您就可以防止 429,然后您就不必担心修复它。
并发限制:您可以限制同时“空中”的请求数量。无限的并行请求会快速满足 RPM 和 TPM 限制。合理的并发上限(例如不超过 10 个并发请求)既可以维持限制,又可以使系统可预测。
断路器:如果提供者不断返回 500/529,则您不必顽强地尝试每个请求,而是“断开电路”一段时间,然后快速使请求失败,而无需发送请求。等待一段时间后,重新打开电路并尝试。此模式可防止您的系统在临时提供程序故障时崩溃。
这三者共同建立了超越单个调用的重试逻辑的系统级弹性。小规模的话,SDK的自动重试就足够了;随着规模的增长,队列、并发和断路器变得不可或缺。它们都有相同的共同目标:向用户反映临时问题,而不是崩溃,而是几秒钟的隐形延迟。
综上所述
当超过速度限制(RPM/ITPM/OTPM)时返回429;这是一个临时错误,将使用重试后和指数退避 + 抖动重试。 500和529也是临时的; 400/401/403/404 是请求/身份问题,无法通过重试解决。强大的流程将错误分为这两组,尝试有限的次数,从前端监控限制并向用户显示平静的消息。
应用任务
考虑一下你的整合。 (1) 列出您可能遇到的错误代码,并将其分为“可重试/永久”。 (2) 写下您的指数回调计划(初始保持、系数、上限、抖动)。 (3) 指定如何使用retry-after 标头。 (4) 编写重试次数耗尽后向用户显示的礼貌消息。
清单
- [ ] 我可以解释 RPM/ITPM/OTPM 限制和 429。
- [ ] 我可以应用指数撤退+抖动+重试后的逻辑。
- [ ] 我可以将错误代码分类为可重试/永久。
- [ ] 我知道我们不应该尝试每一个错误。
- [ ] 我可以向用户显示一条冷静的、面向行动的消息,而不是原始错误。