API 限速被卡之后重发,算不算重复计费?

成本与用量

讲清限速重试里哪些请求会被计费、哪些不会,给做稳定性改造的开发者一套判断标准和排查顺序。

接口一抖就重发,是很多团队默认的做法;但账单出来发现调用次数比预期多,就开始怀疑是不是重发被重复扣费。这篇不讲退避算法本身,只解决一个问题:被限速拦住的那次请求,到底算不算钱。会给你一张按结果分类的对照表,以及怀疑被多扣时按什么顺序去核。

接口一抖就重发,是很多团队默认的做法。等账单出来发现调用次数比预期多,就开始怀疑是不是重发被重复扣了费。这个问题得拆开看:限速被拦下的那次,和已经被受理并产出结果的那次,在计费上根本不是一回事。

这篇不聊退避算法怎么写,只解决一个判断问题——被限速挡住之后重发,钱到底花在哪一次上。给一套按结果分类的对照表,再给一个怀疑被多扣时的核对顺序,照着做完基本能自己下结论。

先分清:一次请求在计费上算不算「发生过」

判断的锚点是服务端有没有真正开始处理并产出计费单元,而不是你客户端发了几次。没进到处理环节的请求,通常不会产生用量记录。所以「我发了三次」和「我被计了三次」是两件独立的事,别混着推。

请求结局通常是否计费原因
被限速直接拒绝一般不计费还没进入推理阶段,没有产出
鉴权失败或参数校验不过一般不计费处理链路在入口就断了
连接没建立就断开一般不计费没有产生任何处理行为
返回了部分内容再断开按实际产出计费已经生成过用量,按已有计费项结算
拿到完整输出但客户端超时重连往往已经计费服务端算完了,只是回程丢了

这张表只是通用规律,各家口径不完全一样。真正靠谱的做法是以你自己的用量记录为准,到 真实用量榜(/usage) 看当时的记录条数和统计口径,再到 官方 API 价格(/official-api) 对照同类调用是怎么归项的。数字会变,判断逻辑不变。

四种常见重发写法,分别会不会多花钱

同样叫「重发」,代价差别很大。下面四种是团队里最常见到的写法,看清楚各自的钱花在哪。

  • 无脑重发同一个请求:如果第一次就是被限速挡下,重发很多次也不计费;但只要其中一次真的被受理,那一次就正常计入用量。风险在于你并不知道第几次会过。
  • 超时后重发:最容易吃亏的一种。服务端可能已经算完并扣了用量,只是响应回程丢了,你的重发等于又买了一次。
  • 流式中断后重连:关键看你有没有从头再发。从头再发就是新的一次请求,已经收到的部分不会因为中断而退回。
  • 换源降级重发:换了站点或换了模型,就是另一笔账。别把两边的用量记成一次调用的成本,对账时会看不出问题在哪。

怀疑被重复扣费,按这个顺序核

直接去找客服说「你们多扣了」通常效率很低。先把可以自己确认的部分做完,剩下的差额才值得拿去问。下面四步不要跳,前一步的结论会决定后一步要不要做。

  1. 第一步:翻客户端日志确认同一条业务请求实际发出去几次,带上请求标识和时间戳。这一步能排除掉大部分「其实是我自己发了两遍」的情况。
  2. 第二步:对服务端用量记录把你发出去的次数和计费记录条数放一起比。条数对不上的那个差额,才是真正需要问的部分。
  3. 第三步:对齐计价口径同一次失败重发,在不同站点可能分别记在请求数上或记在 token 上。先到 pricing-alignment-basics(/pricing-alignment-basics) 把口径理一遍再下结论,否则容易把两种计法当成重复扣费。
  4. 第四步:带着证据去问时间窗口、请求标识、差额数字三样凑齐,比空口描述有用得多。谁的记录对不上就说清楚是哪一笔。

什么情况下这套顺序不适用:如果你的调用量很大且做了采样日志,第一步的「发了两次」可能只是采样误差,得先确认日志是不是全量再往下走。

把重试做便宜:改造时该定的几个规矩

与其事后对账,不如在稳定性改造时就把规矩定死。目标不是不重试,而是让每一次重试都有明确的触发条件和明确的记录,事后一眼能看出钱花在哪种情况上。

只对限速类错误自动重试
限速被挡通常不计费,重试成本接近零;超时类错误不要无脑重试,先判断这次请求是否已经有产出。
重试要有上限和总时长
别让一次任务在后台悄悄重发到天亮。具体闸门怎么设,见 budget-alert-five-gates(/budget-alert-five-gates)。
重试次数与成功次数分开记
两个指标混在一起,月度核对时就分不清哪些调用是有效产出、哪些只是白跑。
给每条请求打上标识
同一个标识的重发记录能串起来看,对账时不需要靠时间猜。

什么情况下这套不适用:如果你的调用是按次包月而非按量计费,重试对单次成本的影响会小很多,重点应该转到限速会不会拖慢整体吞吐,而不是抠单次费用。

下一步先去站内把自己的用量记录翻出来,对一遍最近一次限速重试前后的条数差,再决定要不要改重试策略。

常见问题

被 429 挡下来的请求,会不会也算我一次调用?

通常不会。429 是服务端在推理开始之前就把请求挡回来了,没有产出任何计费单元。但要注意,如果你的计费口径是按「发起的请求数」而不是按产出计,那就要以站点实际记录为准,别默认它不计。核的方式是拿同一时间窗口的用量记录和日志对一遍。

超时重发最容易多花钱,为什么?

因为超时和限速不一样,超时往往发生在服务端已经算完、只是在返回路上丢了响应。这时候用量已经产生,你的客户端却以为失败又发了一次,于是同一条业务请求买了两次单。稳妥的做法是给请求加上可复用的标识,重发前先确认上游有没有已经处理过。

重试到底该不该开自动?

分错误类型看。限速类可以开,但要带上退避和次数上限;超时类建议先做一次状态确认再决定重发;参数错误、鉴权错误这种重发也没意义,纯粹白跑。判断标准不是「能不能重试」,而是「这次重试有没有可能换来个不一样的结果」。

本文依据各平台公开文档与官方公告整理,只做中文归纳;具体做法、参数与限制以官方文档为准。