简介:某大模型平台单日两度出现API与对话服务中断,且首次修复后再度波动。本文拆解此类故障对调用方的真实影响,从请求失败、重试风暴到幂等与成本风险,并给出一套可落地的稳定性建设方案:精细超时、指数退避重试、熔断降级、多通道容灾、异步削峰与全链路可观测,帮助开发者把外部故障对业务的影响压到最低。
11月3日下午,某大模型平台先后两次发布服务公告:16时58分,其网页端与API服务出现部分中断,经修复一度恢复正常;18时25分,服务再度出现部分中断,波及多个模型版本的API调用与对话服务,官方表示已实施修复并持续监控修复效果。
两个细节值得开发者放大审视。
第一,“部分中断”是最难处理的一类故障。 它不是全局宕机,而是部分流量、部分实例或部分功能受损。对调用方而言,请求时而成功、时而失败,错误率剧烈抖动。如果没有按通道、按错误码分组的细粒度监控,这种状态极易被误判为自身网络抖动或代码缺陷,白白消耗宝贵的排查时间。
第二,“修复后再中断”说明首次修复大概率只是应急止血。 根因并未被彻底消除,恢复期的系统常处于“半健康”状态:容量尚未完全回填、缓存冷启动、流量回切还会形成二次冲击。把“恢复公告”直接当作“稳定信号”,是许多事故复盘中反复出现的教训。
再叠加舆论层面“又崩了”的观感,可以得出一个明确的工程判断:在大模型深度进入生产链路的今天,外部API波动已经从偶发事故,演变为必须在架构层面正面设计的常规风险。
1. 请求层故障:超时、错误码与流中断。 连接重置、网关超时、5xx错误集中出现;容量紧张时,限流类错误(如429)往往先于彻底故障出现,是最值得捕获的“前兆信号”。流式输出场景还多一类问题,响应中途断流,拿到半截结果。如果下游没有完整性校验,半截内容会直接污染业务数据。
2. 重试风暴的放大效应。 失败本身并不可怕,可怕的是所有调用方在同一时刻集体重试。若客户端没有退避与抖动机制,一次几十秒的服务抖动就会被放大成持续数分钟的请求洪峰,反过来延长对方的故障时间,也拖垮自己的接入层。
3. 业务功能受损。 摘要、生成、分类、智能问答等直接依赖模型能力的功能整体降级;如果调用位于关键路径(如交易审核、实时助手),用户看到的就不是“变慢”,而是“不可用”。
4. 成本与数据一致性风险。 超时后盲目重试,可能造成同一任务被重复推理、重复计费;写入类操作若未做幂等设计,还会产生重复数据。此外,故障恢复瞬间积压流量的集中回放,也可能把短时成本推高。
5. 排查与沟通成本。 “部分中断”最容易误导团队先查自身链路;同时用户问询压力上升,研发被迫在排障与应答之间来回切换,进一步拖慢整体恢复节奏。
理解脆弱性来源,才能对症下药:
核心思路只有一句话:不要把宝押在“外部服务永远稳定”上,而要让自己的系统在它不稳定时依然可用。以下实践按投入产出比排序。
先谈超时。要区分连接超时与读超时:连接超时可设得较短(如3~5秒),快速失败;流式场景的读超时应适当放宽,但同时要设置“无进展超时”,若连续N秒没有收到任何新内容,即判定连接僵死并主动断开。
再谈重试,四条原则:
示意代码:
import time, randomRETRYABLE = {408, 429, 500, 502, 503, 504}def call_llm(payload, max_retries=4):for attempt in range(1, max_retries + 1):try:resp = http_client.post( # 统一封装的HTTP客户端endpoint, json=payload,timeout=(5, 60), # (连接超时, 读超时))if resp.status == 200:return handle_stream(resp)if resp.status in RETRYABLE:wait = resp.headers.get("retry-after")sleep_for = float(wait) if wait else backoff(attempt)else:raise NonRetryableError(resp.status)except (TimeoutError, ConnectionError):sleep_for = backoff(attempt)if attempt < max_retries:time.sleep(sleep_for)raise AllRetriesExhausted()def backoff(attempt):# 指数退避 + 随机抖动,避免重试风暴return min(2 ** attempt, 30) + random.uniform(0, 1)
当某个通道的错误率或失败次数超过阈值,熔断器打开,后续请求直接走降级路径,既避免无谓冲击下游,也给对方恢复留出时间。冷却期结束后进入半开状态,放行少量探测请求,成功则关闭熔断器,失败则重新打开。
class CircuitBreaker:def __init__(self, threshold=10, cooldown=60):self.threshold, self.cooldown = threshold, cooldownself.fails, self.state, self.opened_at = 0, "closed", 0.0def allow(self):if self.state == "open":if time.time() - self.opened_at > self.cooldown:self.state = "half_open" # 冷却结束,放行探测return Truereturn Falsereturn Truedef record(self, ok):if self.state == "half_open":self._reset() if ok else self._trip()elif ok:self.fails = 0else:self.fails += 1if self.fails >= self.threshold:self._trip()def _trip(self): self.state, self.opened_at = "open", time.time()def _reset(self): self.state, self.fails = "closed", 0
降级策略应当分级设计,按代价从低到高依次考虑:
在业务代码与大模型API之间引入统一抽象层,业务侧只面向“能力”编程,不感知具体通道。抽象层负责主备路由、按健康度打分选路、故障时自动切换。
需要特别提醒:不同通道在模型效果、参数语义、上下文长度、计费方式上存在差异,抽象层不能只做协议适配,还应保留每条通道的“能力描述”,让路由决策既看健康度,也看任务要求。
class Channel:name: strdef chat(self, messages, **kw): ...class FailoverRouter:def __init__(self, channels):self.channels = channels # 按优先级排列def chat(self, messages, **kw):last_err = Nonefor ch in self.channels:if not breaker_of(ch).allow():continuetry:result = ch.chat(messages, **kw)breaker_of(ch).record(True)return resultexcept TransientError as e:breaker_of(ch).record(False)last_err = eraise AllChannelsDown(last_err)
对非实时场景(批量打标、离线摘要、夜间任务),把请求投递到消息队列,由消费端按稳定速率调用。队列天然提供重试缓冲与削峰能力,高峰期“排队”远优于“直接失败”。实时场景则应缩短用户可见的等待路径,把重试放到后台异步完成。
为每次业务任务生成唯一幂等键,随请求携带并在重试时复用,从源头规避重复推理、重复计费与重复写入。对完全相同或高度相似的输入,可引入结果缓存,既降低成本,也在故障期提供兜底,但需注意缓存时效与数据合规边界。
至少要监控以下指标:按通道/模型/错误码分组的成功率、延迟分位数(P50/P95/P99)、首内容延迟、重试次数、熔断器状态、Token消耗与成本。告警要分级:错误率超阈值持续数分钟触发即时通知;延迟劣化、重试上升触发工单跟踪。同时留存每次故障窗口的调用样本,用于事后复盘与压测回放。
工程落地时,可以自建采集与告警体系,也可以借助百度智能云等云服务商提供的日志服务、监控告警、消息队列、容器平台等通用能力,快速搭建“采集—存储—分析—告警”的闭环,把精力集中在业务侧的路由与降级逻辑上。
选型阶段把稳定性纳入评估。 关注服务商的历史故障频率、公告透明度、限流策略与降级说明。但要清醒:SLA是承诺不是保险,最终兜底永远在自己的架构里。
定期做故障演练。 通过注入超时、错误码、断流等故障,验证熔断、切换、降级链路是否真的按预期工作。没有演练过的预案,大概率在真实事故中失效。
预案文档化。 明确谁有权切换通道、切换的代价与影响范围、回切条件是什么,避免事故现场临场决策。
在产品层面管理用户预期。 依赖AI能力的功能,应当在交互设计上为“生成中”“失败重试”“降级模式”留出明确状态,而不是让用户面对无限转圈。
单日两度中断的本质不是一条新闻,而是一次提醒:当大模型成为生产链路的基础依赖,外部API不稳定就是常态而非例外。真正的工程成熟度,体现在故障发生时用户几乎无感。把超时、重试、熔断、多通道、异步化、可观测这套组合拳打扎实之后,任何一次“某平台又崩了”,对你而言都只是后台的一条告警,而不是一场事故。