ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

AI接口超时重试如何避免费用翻倍?重试策略与计费边界解析

AI接口超时重试如何避免费用翻倍?重试策略与计费边界解析

你有没有遇到过这样的情况:服务上线前压测一切正常,上线后碰上网络抖动,AI接口时不时超时。本着“失败就再试一次”的朴素直觉,你加了一段重试逻辑,日志里“重试成功”的占比还挺好看。结果月底对账时傻眼了——账单金额差不多是预估的一倍。查下来发现,很多请求并不是第一次就失败,而是“第一次读超时被重试,第二次成功返回”。同一个Prompt被模型完整跑了两遍,费用自然收了两遍。

AI接口超时重试,表面看是可用性问题,实际上是一笔隐藏的成本账。这篇文章不聊泛泛的重试机制,就聊清楚一件事:为什么超时后的重试会让你多花钱,以及怎么把重试策略设计成“既保住成功率、又不烧钱”的样子。如果你正准备给AI能力接一个通用HTTP重试工具包,或者正在排查莫名其妙的费用上涨,建议先看完这段。

1. 超时重试让费用翻倍的底层逻辑:计费时间窗和重试的错位

1.1 一次“看起来失败”的请求,其实已经算完钱了

很多人对超时有个根深蒂固的误解:客户端显示超时,就代表这次调用没成功、服务端没干活。这个直觉放在普通HTTP接口上大部分时候成立,但放在大模型接口上非常危险。

这里的核心区别在于:HTTP超时是客户端侧的行为,不是服务端侧的取消指令。客户端说“我等不起了,断开连接”,但请求数据已经通过网络到达了服务端,服务端可能早就把请求放进了推理队列,甚至已经开始生成结果。对大模型来说,生成一旦开始,算力已经在消耗,token已经在产出,计费时间窗就已经打开了。

我举个具体例子。假设你调用一个文本生成接口,客户端设置的读超时是5秒。某个时刻服务端排队严重,请求发过去后一直处于排队或者推理状态,客户端在5秒后抛出Timeout异常。你判断“这次失败了”,于是立刻重试,第二次请求因为队列恢复畅通,3秒就返回了成功结果。

从你的视角看,业务是成功的;从账单的视角看,第一次请求实际上在第7秒左右完成了全部生成,输出token全额计费,第二次请求也正常计费。一次业务调用,两笔完整扣费。重试得越果断,账单越难看。

这个现象用一个生活化的类比更好理解:你打电话没打通,以为对方没听到留言,于是又打了一遍。但对方其实已经听到了第一次的留言并回复了你,你为两次通话都付了钱。区别在于,电话公司会给你详单,而AI平台的账单往往只显示token消耗,你很难把“超时的那一次”和“重试成功的那一次”对上号。

1.2 大模型接口的慢、贵、非幂等,放大了重复扣费风险

为什么这个坑在普通HTTP接口上不明显,偏偏在AI接口上特别突出?因为大模型接口有三个普通接口没有的特点,三个加在一起,构成了重复计费的完美条件。

慢。普通业务接口一般要求响应在几百毫秒到一两秒内返回,超时阈值设得保守一点也不太容易误伤。大模型接口正常响应就需要数秒甚至十几秒,长文本生成场景下几十秒也不罕见。超时阈值稍微设小一点,大量本可以成功的请求就会被误判成超时。

贵。普通接口往往按次收费,一次没成功就是没产生费用。大模型接口按token计费,重试不是“再试一次连接”,而是让模型把同样的Prompt从头生成一遍。输入token要算,输出token要算,哪怕第二次生成的答案和第一次完全不同,两轮生成的费用都真实发生了。

非幂等。普通写操作可以通过幂等键去重,同一个业务ID只执行一次。大模型平台的底层接口很少提供类似“幂等键”的机制,同一个Prompt调用两次就是两次独立计费的完整推理过程。你在应用层很难用简单的去重逻辑避免重复扣费,因为平台并不知道你的两个请求其实是同一次业务操作。

还有一个容易被忽略的细节:服务端排队。大模型服务在高负载下通常有排队机制,客户端读超时发生时,请求可能还在队列里没开始推理。你重试的新请求又排到队尾,表面上重试成功了,但老请求在队列里并不会被取消,最终还是会进入推理阶段并计费。也就是说,即使第一次请求在超时那一刻“确实没在干活”,它依然会在你重试之后悄悄跑完,我见过不少案例都是这个原因导致费用异常。

普通HTTP接口和大模型接口的对比如下表:

维度普通HTTP接口大模型AI接口
响应耗时通常几十毫秒到几秒通常几秒到几十秒
计费方式按次、按时长,失败可不计费按token,生成即计费
幂等机制可设计幂等键去重一般不提供,重复调用即重复计费
超时后的服务端行为可能已取消或事务回滚通常继续执行完成
重试风险低,损失主要是延迟高,直接造成费用翻倍

1.3 连接超时、读超时、总超时,踩中哪个才会多扣钱

要判断一次超时重试是否安全,首先要搞清楚你踩中的是哪种超时。很多人只知道“我设置了超时”,但不知道超时内部还分好几个阶段,不同阶段对应完全不同的重试风险。

连接超时发生在TCP握手阶段,客户端还没有把请求体发送出去,服务端没有收到任何业务数据,此时重试是相对安全的,大不了就是多试几次连不上。

读超时发生在请求已经发送完成、正在等待响应的阶段,这是最危险的重试场景。请求已经进入了服务端的处理管道,计费边界大概率已经跨过去了。读超时可能只是“响应慢了”,而不是“没被处理”。

还有一类流式接口的空闲超时,在SSE或流式响应场景下,客户端等待下一个数据包的时间超过阈值就会断开。大模型流式输出时两个数据包之间间隔变长很常见,一旦断开,服务端不会马上停止生成,已生成的token照样计费。

下表可以帮你快速定位不同超时类型的重试风险:

超时类型判断依据服务端状态重试安全性
连接超时TCP握手未完成未收到请求数据基本安全,可重试
读超时请求已发送,响应未返回已进入处理或队列高风险,谨慎重试
总超时整次调用超过硬性上限视触发阶段而定需根据当前阶段判断
流式空闲超时数据包间隔超限可能仍在生成已产生token,风险高

判断能不能重试,关键不是看异常类型名,而是看请求是否已经跨过了计费边界。这个边界在连接建立的那一瞬间就已经存在了,所以读超时的重试一定比连接超时的重试危险得多。

2. 最容易多花钱的四种重试写法

理解了上面的计费逻辑之后,再回头看代码里常见的重试写法,几乎每一条都踩在雷区上。我在实际代码审查里见到最多的,就是下面这四种。

2.1 “失败就立刻重试”的三连击

很多同学第一次接AI接口时,会写出这样的代码:

for attempt in range(3): try: resp = client.post(url, json=body) return resp.json() except Exception: time.sleep(0) continue

这段代码的逻辑很简单:失败就马上再来一次,最多试三次。但它完全没有区分失败的类型,也没有等待时间。如果服务端因为过载而超时,你的重试只会加重服务端负担,导致下一次请求超时的概率更高。如果超时发生在读阶段,那第一次请求可能已经在服务端跑完了,第二次又跑一遍,第三次大概率也没被浪费。

我在一个内部工具里见过更夸张的版本:循环10次,间隔0.5秒。某个业务高峰时段,一次用户请求最多产生11次模型调用,其中10次是重试出来的。那次故障后我们拉账单,发现当天该业务的模型费用是平时的6倍。

失败就立刻重试,本质上是用钱换成功率。对不花钱的接口可以这么干,但对token计费的AI接口,这个写法的成本高到你无法接受。

2.2 把所有超时都当成连接失败

有些同学知道要区分异常类型,但处理得比较粗糙,只判断了“是不是超时异常”,没有进一步判断是连接超时还是读超时。

try: resp = client.post(url, json=body) except httpx.TimeoutException: # 不管三七二十一,重试 time.sleep(1) resp = client.post(url, json=body)

连接超时基本可以安全重试,这个判断没错。但读超时也落到了同一个异常分支里,问题就大了。读超时意味着请求已经进入服务端,重试一次就等于发起两次推理。

真实的HTTP客户端里,连接超时和读超时通常会有不同的异常类型,或者同一个异常类但带有不同的内部字段。你要做的不是把所有超时都丢进同一个重试桶里,而是拆开判断。连接阶段超时走“安全重试”分支,读取阶段超时走“高风险”分支——要么不重试,要么只允许非常有限的弥补策略。

2.3 全局超时一刀切,把长生成任务反复误杀

更隐蔽的问题是超时参数本身设置不合理。有的项目直接把超时设成5秒,理由是“普通HTTP接口不都是这个配置吗”。但大模型接口生成一段200字的文案可能都要6到8秒,生成一篇长文更是要十几秒。

这种情况下,正常的请求会反复触发超时,反复重试。从应用日志看,“第一次失败,第二次成功”,系统可用性好像没问题。但从计费数据看,每次业务调用都产生了两次甚至三次完整计费。

假设你的读超时是5秒,重试次数是3次,那么一次业务请求最多会产生4次模型调用。最坏情况下,你以为自己在处理一次请求,实际上付了4次生成的钱。

正确的做法是按请求的实际规模动态调整超时,而不是全局写死一个常量。生成内容越长的请求,超时阈值就应该越大。这一点在下一章我会给出具体的计算思路。

2.4 流式接口断连后,把整个请求从头重放

流式接口是重灾区,因为很多人把流式调用当成普通HTTP调用一样处理,一超时就重新请求。但流式场景下,服务端可能在客户端断连之前已经输出了大量token,这些token是已经计费的。你从断连处重新发起整个请求,等于又买了一次完整的生成过程。

举一个我实际遇到的例子。一个流式翻译服务,用户输入一段长文本,模型以SSE方式逐个token返回。某天网络不稳,客户端经常在响应中途读超时,SDK内部默认重试一次。用户那边看到的结果是“偶尔卡顿但最终成功了”,但后台统计显示,大约三成请求实际被执行了两遍,其中第一遍往往已经翻译到一半,产生了近一半的输出token费用。

如果你用的是流式接口,重试策略绝对不能参考普通请求。要么完全不自动重试,要么重试前先去平台侧查询当前请求是否已经产生了消耗,确认没有计费记录再重发。很多平台上流式任务的状态查询能力有限,但至少你要知道这个风险的存在,而不是盲目重试。

3. 正确的重试姿势:分层超时、错误分类与指数退避

理解了反面案例,接下来进入正题。一套在AI接口场景下相对稳妥的重试策略,至少包含三块:错误分类、动态超时、指数退避加抖动。

3.1 先把错误分类,再决定要不要重试

所有重试决策都应该基于一个前提:这次失败的性质是什么。我习惯把AI接口的错误分成四类,每一类的重试策略完全不同。

连接类错误,包括连接超时、DNS解析失败、连接被拒绝等。这类错误发生时请求大概率没有到达服务端,计费边界没有跨过,可以按照正常的指数退避重试。

读取类错误,包括读超时、连接中断、响应解析失败等。这类错误代表请求已经提交给了服务端,服务端很可能已经开始了推理计费。重试要极其克制,我的默认策略是:允许重试,但最多一次,而且在重试前记录一条明显的警告日志,方便事后核对费用。

服务端错误,包括HTTP 429、500、502、503等。429是限流,必须尊重服务端的Retry-After头;5xx是服务端异常,可以重试但要设置次数上限。这类重试不会直接导致重复计费,因为服务端明确返回了错误,但如果服务端在返回错误前已经完成了部分生成,账可能还是会算。

客户端错误,比如400、401、403、422等。这类错误说明是你自己的请求有问题,重试一万次也一样,直接返回错误给调用方,不做任何重试。

分类结果可以用一个决策表来表示:

错误类型是否重试等待策略最大次数
连接超时/连接失败可重试指数退避+抖动3次
读超时/连接中断极谨慎仅限1次1次
HTTP 429可重试按Retry-After或退避2次
HTTP 500/502/503可重试指数退避+抖动2次
HTTP 400/401/403/422不重试—0次

在实际编码时,我会把上面的逻辑封装成一个决策函数,输入异常类型和HTTP状态码,输出“是否重试”和“等待时间”。这样重试逻辑就变成了一条清晰的规则链,而不是一堆if嵌套。

3.2 超时时间不是拍脑袋定的:按响应规模反推预算

前面说过全局超时一刀切会误杀长生成任务,那正确的超时该怎么设?我采用的方法是按“预期输出规模”反推一个合理的读超时。

思路是这样的:已知模型平均输出速度大概是每秒多少token,再根据当前请求的max_tokens设定预期输出上限,两者相除得到理论耗时,然后加上固定的缓冲时间。这个公式计算的就是“这件事正常干完需要多久”。

def estimate_read_timeout(max_output_tokens: int, avg_output_rate: float = 12) -> float: # avg_output_rate 按主要模型实测的 p50 输出速度估算 estimated_seconds = max_output_tokens / avg_output_rate buffer_seconds = 10 return estimated_seconds + buffer_seconds

举个例子,你的请求设置了max_tokens=512,估算输出速度是每秒12个token,那理论耗时就约是512除以12,约43秒,加上10秒缓冲,读超时设在50秒以上才合理。如果你的业务平均只生成50个token,那理论耗时约4秒,缓冲10秒后设14秒也够了。

读超时设置的关键是区分长任务和短任务,而不是给所有请求一个固定值。实际运维中,我不会用理论值直接定死,而是先跑一周统计真实调用的耗时分布,取响应耗时的p95作为估算基准,再叠加缓冲。这样既不会频繁误杀,也不会因为超时太长导致故障恢复变慢。

3.3 指数退避加抖动,重试次数按成本设上限

放弃了“失败立刻重试”,又该如何控制重试节奏?通用的做法是指数退避加抖动。指数退避保证两次重试之间的间隔随着次数增长,避免在服务端过载时形成连续打击;抖动的作用是打散多个请求的重试时间点,防止大量客户端同时进入重试循环,形成“重试风暴”。

退避公式我常用下面这个:

import random def compute_backoff(attempt: int, base: float = 1.0, cap: float = 10.0, jitter: float = 1.0) -> float: # attempt 从 0 开始 return min(cap, base * (2 ** attempt)) + random.uniform(0, jitter)

当attempt=0时,基础等待1秒,加0到1秒的随机抖动;attempt=1时,基础等待2秒,加随机抖动;attempt=2时,基础等待4秒。整体等待序列大致是1到2秒、2到3秒、4到5秒,封顶在10秒左右。对于AI接口来说,这个节奏已经足够缓和,再慢就会明显影响用户体验。

重试次数上限也要单独说。普通接口设个3次5次问题不大,但AI接口每次重试都是真金白银。我一般会把自动重试上限压到2到3次,同时区分场景:后台批量任务可以允许2次重试,用户同步请求最多允许1次,涉及扣费操作的请求则直接禁止自动重试。

3.4 一个偏稳妥的智能重试封装示例

把前面的分类、退避和日志串起来,可以写一个简化但完整的调用封装。以下代码用httpx举例,思路同样适用于requests或openai官方SDK:

import random import time import uuid from dataclasses import dataclass import httpx @dataclass class RetryDecision: should_retry: bool wait_seconds: float reason: str def compute_backoff(attempt: int, base: float = 1.0, cap: float = 10.0, jitter: float = 1.0) -> float: return min(cap, base * (2 ** attempt)) + random.uniform(0, jitter) def make_retry_decision(exception: Exception | None, response: httpx.Response | None, attempt: int) -> RetryDecision: if response is not None: status = response.status_code if status in (400, 401, 403, 404, 422): return RetryDecision(False, 0, f"client error {status}, no retry") if status == 429: return RetryDecision(True, compute_backoff(attempt), "rate limited, backoff") if status in (500, 502, 503): return RetryDecision(True, compute_backoff(attempt), f"server error {status}, backoff") return RetryDecision(False, 0, f"unexpected status {status}") if isinstance(exception, httpx.ConnectTimeout): return RetryDecision(True, compute_backoff(attempt), "connect timeout, safe to retry") if isinstance(exception, httpx.ReadTimeout): # 读超时风险高:请求可能已在服务端执行,只允许一次重试 if attempt < 1: return RetryDecision(True, compute_backoff(attempt), "read timeout, limited retry") return RetryDecision(False, 0, "read timeout, max attempts reached") if isinstance(exception, httpx.ConnectError): return RetryDecision(True, compute_backoff(attempt), "connect error, safe to retry") return RetryDecision(False, 0, "unknown error, no retry") def call_with_retry(url: str, payload: dict, max_retries: int = 2): request_id = str(uuid.uuid4()) attempt = 0 while True: try: headers = { "X-Request-Id": request_id, "X-Request-Attempt": str(attempt), } with httpx.Client(timeout=httpx.Timeout(connect=3.0, read=estimate_timeout(payload))) as client: response = client.post(url, json=payload, headers=headers) if response.status_code >= 400: decision = make_retry_decision(None, response, attempt) else: return response.json() except Exception as exc: decision = make_retry_decision(exc, None, attempt) if not decision.should_retry or attempt >= max_retries: # 记录决策日志后返回失败 print(f"request_id={request_id} attempt={attempt} decision={decision.reason}") raise RuntimeError(f"request failed: {decision.reason}") print(f"request_id={request_id} attempt={attempt} retry_after={decision.wait_seconds:.2f}s reason={decision.reason}") time.sleep(decision.wait_seconds) attempt += 1

这个封装的核心在于:连接超时走安全重试,读超时只额外给一次机会,4xx完全不重试,429和5xx按退避节奏来。每一条判断都有明确的计费依据,而不是无脑再来一次。

4. 用请求ID与重试决策日志,把每一笔账都对清楚

策略定好了,还差观测手段。很多团队直到月底账单吓一跳才发现问题,就是因为重试过程完全没有日志和ID追踪。你需要一套能让“本地失败记录”与“平台计费记录”互相佐证的方法。

4.1 全链路请求ID:重试时保留同一个ID,但要标记尝试序号

每次调用AI接口时,在应用层生成一个全局唯一的请求ID,放进HTTP请求头传给平台,同时在本地日志中记录。重试时保留同一个请求ID,另外用单独的头或者参数标记当前是第几次尝试。

为什么保留同一个ID?因为如果平台侧日志里能看到你传入的请求ID,你就可以把“第一次超时的请求”和“重试后的成功请求”关联起来。很多平台不直接在账单里展示业务自定义的请求头,但技术支撑排查时往往能查到。即使平台侧查不到,你本地也能根据请求ID把两次尝试拼成一条完整记录。

实际代码里只需要两三行:

import uuid request_id = str(uuid.uuid4()) headers = { "X-Request-Id": request_id, "X-Request-Attempt": str(attempt), }

额外的X-Request-Attempt头用来区分同一条请求的第几次尝试。排查时只要在日志里搜索request_id,就能看到完整的重试时间线:第一次什么时间、什么错误、隔了多久发起第二次、第二次最终是否成功。

4.2 重试决策日志里必须有的字段

很多团队的重试日志就一句“retry after xxx seconds”,信息量完全不够。我建议每一条重试决策都记录成结构化日志,至少包含下面这些字段:

字段示例用途
request_id3f2c9a1e-6d5a-4c8f-b0e2-1a7d9c8b6f4a串联同一次业务调用的所有尝试
attempt0, 1, 2第几次尝试
modelgpt-4o-mini区分不同模型成本
prompt_hashsha256:ab12...识别相同Prompt是否重复计费
max_tokens512估算这次请求的理论耗时和成本
error_typeread_timeout失败分类
phaseread请求处于连接还是读取阶段
elapsed_ms5012这次尝试实际耗时
decisionretry_limited重试决策结果
next_retry_ms2300下次重试等待时间
server_request_idchatcmpl-...(如有)平台侧返回的请求标识

有了这些字段,你可以随时回答三个问题:哪些请求被重试过?为什么被重试?重试之后平台侧有没有对应多次计费记录?排查费用异常时,这三个问题就是全部抓手。

我在实际项目中会把这种日志写进独立的文件或者日志流,而不是混在普通业务日志里。因为重试日志的查询频率很高,单独存放能让你用grep或者日志平台快速拉出所有重试事件,不用在一大片业务日志里翻。

4.3 用prompt哈希与时间窗核对账单,找出双倍扣费

光有日志还不够,要证明“多付了钱”,需要拿本地的重试记录和平台的用量明细做交叉核对。

第一步,本地对每个请求的请求体做一个哈希,比如把system prompt、user prompt、model、temperature、max_tokens这些参数拼起来,算出一个prompt_hash。

第二步,从平台的用量明细或者账单接口导出计费记录,按模型、请求时间、token数量等维度整理好。

第三步,用prompt_hash和时间窗做匹配:找出那些在同一个时间段内、同一个prompt_hash出现了两条或以上计费记录的请求。这些候选记录里,大概率就有“超时后被重试”的双倍计费项。

用SQL的思路大概是这样的:

SELECT prompt_hash, request_id, started_at, duration_ms, attempts FROM inference_logs WHERE date = '2025-11-01' AND attempts > 1 ORDER BY prompt_hash, started_at;

如果本地日志准确记录了attempt次数,这条SQL能直接告诉你哪些请求重试过。再配合平台用量明细看对应时段是否有多条消费记录,就能锁定重复扣费的证据链。

我自己的习惯是每周跑一次这个核对脚本,输出一份“重试导致潜在重复计费”的清单。平时看着没什么用,一旦费用趋势异常,这份清单就是最有力的排查起点。

5. 针对AI接口调用方的高成本重试策略建议

有了技术手段之后,还有几个更上层的策略问题需要想清楚。很多团队栽跟头,不是因为不会写重试代码,而是没有建立“重试是有成本的”这个意识。

5.1 用户主动操作场景:宁可报失败,也别悄悄重试

在用户主动触发AI生成的场景里,我现在的默认策略是:超时之后不自动重试,直接告诉用户“生成超时,请再试一次”,由用户决定要不要重新发起。

原因很直接:如果系统偷偷重试成功,前端会展示出一次成功生成的结果,用户会认为这次操作只消耗了一次生成费用。但在账面上,第一次超时的请求和第二次重试的请求都已经计费。用户不知道,你自己也容易忽略,直到对账时才发现费用不对。

更麻烦的是生成结果不一致的问题。第一次请求可能已经生成了一半内容,只是超时没返回;第二次重试又生成了一版完全不同的内容。用户最终看到的是第二版,但第一版已经消耗的token费用也挂在你的账上。这个成本用户感知不到,但它是真实存在的。

所以,涉及用户主动提交的操作,我的经验是把重试选择权交还给用户,在界面上提供“重试”按钮,而不是在后台默默重发。如果业务确实需要自动重试,至少要在日志中标记清楚,同时要确保产品负责人知道这个操作会带来额外的模型费用。

5.2 给每次生成请求设置“重试预算”

重试预算是我最近一年才养成的习惯。所谓预算,就是在代码里给自动重试设置一个明确的成本上限,而不是让它无限制地循环下去。

单次请求的成本可以根据预估输入输出token数和模型单价算出来,一次请求如果最多重试R次,最坏成本就是单次成本乘以R加1。这个数字应该在设计重试策略时就确定下来,而不是等账单出来再去追问。

例如,某次请求的单次成本是0.02元,如果设置无上限重试,某次故障时一个请求重试了10次,成本就变成0.22元,单看不多,但乘以请求量就很可观。反过来,如果明确设定最多重试2次,那最坏成本就是0.06元,预算可控,心里有数。

更进一步,我会在网关层做一个全局的重试预算熔断器:统计当前小时内自动重试的总次数,一旦超过预设阈值,就暂时关闭自动重试,所有超时请求直接返回失败,避免故障期间的重试风暴烧掉大量费用。这个熔断并不复杂,用计数器加定时重置就能实现,但它能在极端情况下守住成本底线。

5.3 压测时别只压正常路径,重点测“超时+重试”组合场景

最后分享一个压测层面的建议。常规压测只关心正常路径的吞吐和延迟,但这个习惯在AI接口场景下会漏掉一类重要问题:超时和重试组合起来时,费用会膨胀到什么程度。

我建议在压测计划里加入一个专门的场景:用本地mock服务模拟“有一定概率响应特别慢”,把慢响应比例调到10%到30%,同时让客户端采用短读超时加自动重试的策略。然后对比两个数字:成功返回给调用方的次数,以及实际发往模型端的计费请求次数。

理想情况下,这两个数字应该接近1比1,说明重试几乎没有制造额外计费。如果计费请求数明显大于成功次数,说明重试策略正在消耗大量预算,压测报告里就应该预警这个问题。

实现这个mock很简单,不必真实调用大模型平台。本地起一个HTTP服务,在响应前随机sleep几秒,客户端正常走真实的重试逻辑,就能模拟出“读超时后重试成功”的完整链路。跑一轮下来,你能直观看到每一次重试会带来多少额外计费请求。

我现在的习惯是,把这套“超时+重试”压测纳入每个AI服务的上线卡点。压测通过后,再配合前面的请求ID日志和账单核对脚本,线上费用基本不会出现莫名其妙的翻倍情况。毕竟,重试本身不是问题,问题是重试的时候没人算过账——等账单教你怎么算账,就晚了。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进