
从昨天晚上开始我的朋友圈和好几个技术群就被“千问崩了”刷屏了。一开始我以为是某个独立部署的模型实例出了故障仔细一看是阿里巴巴的通义千问大规模服务异常官网、API 接口都出现了不同程度的响应超时、报错甚至直接不可用。作为一个深度依赖大模型 API 做应用开发的从业者这个场景我太熟悉了但这次影响面之大、持续时间之长确实值得认真复盘一次。这篇内容我不打算去复述官方公告或者新闻通稿而是想从一个云上应用开发者和架构师的视角把这次“崩了”背后的技术链路、真正脆弱的环节以及我们这些做大模型应用的人应该从中吸取什么教训一条一条拆开来讲。无论你是自己搭过模型服务还是只是调用 API 做业务这篇文章都能帮你理解为什么一个“对话接口”会崩得这么彻底以及我们能在自己的系统里做哪些事来避免被这样的故障一波带走。1. 从用户视角还原“千问崩了”的几个小时1.1 用户侧实际看到了什么故障的直观表现各个渠道用户的反馈其实高度一致。首先是官网对话框的响应明显变慢从正常的秒级出字变成十几秒甚至几十秒没有任何 token 返回随后页面直接提示“服务繁忙请稍后重试”。API 端的表现更典型调用方陆续收到大量 5xx 错误特别是 502 Bad Gateway 和 504 Gateway Timeout也有部分请求直接连接超时压根没进到后面的推理环节。还有一些比较隐蔽的现象值得关注。比如部分已经建立的流式连接SSE在生成到一半时突然中断客户端收不到完整的流结束标记比如有些请求返回了 200 状态码但响应体是空的或者只有一个空 choices 数组。这种“半成功”的失败比直接报错更折磨人因为你的服务端很可能已经把这个 200 响应当作正常结果处理了下游的数据完整性就会出问题。1.2 故障的时间线和影响范围从公开信息和技术群的讨论看这次故障不是瞬间崩盘而是经历了一个逐步恶化的过程。一开始可能是部分区域、部分模型的请求延迟升高随后逐步扩散到大范围的超时和错误这个过程持续了一段时间后才开始恢复。对于做在线业务的人来说这种“温水煮青蛙”的恶化方式是最麻烦的因为系统容量监控往往有滞后性等到告警触发时故障已经扩散到了用户侧。影响范围也不只是网页端和 API 端。不少第三方应用、AI 编程助手、对话机器人都是直接或间接依赖千问的 API尤其是那些把千问作为默认模型的服务几乎等于跟着一起瘫痪了。我甚至看到有做 SaaS 的同行吐槽他们平台的错误率一夜之间从 0.1% 飙升到 40%技术支持的微信直接被打爆客户根本分不清“你的服务挂了”和“上游模型挂了”只会认为是你的产品不稳定。1.3 一个关键信号有降级但不够彻底从部分开发者抓包和反馈的情况看故障期间网关层面其实尝试过降级。比如有些请求被降级到其他模型部分非核心功能关掉了联网搜索、图片生成等增值服务目的应该是先保住核心对话链路。但实际效果并不理想因为降级后的模型容量很快也被打满了再加上降级策略本身也占用了网关的处理资源最终表现为整体服务质量进一步下滑直到彻底熔断。这其实暴露了一个很现实的问题大模型的降级方案和传统微服务的降级完全是两码事。传统服务降级可能只是返回一个默认值或者缓存数据但大模型的降级需要切到另一套推理集群而一旦两个集群都依赖同一份底座资源或者同一个接入网关降级就变成了从一个瓶颈挪到另一个瓶颈。2. 一个推理请求要穿过多少道关卡才会“崩”2.1 从 DNS 到网关的第一道门一次千问 API 调用从客户端发出到拿到结果中间要经过的环节远比大多数人想象的多。第一步是 DNS 解析接着请求打到 CDN 或云负载均衡然后进入 API 网关这个环节负责鉴权、限流、路由、协议转换是整个链路里最容易被流量冲垮的地方。网关的问题在于它不仅在转发请求还在做大量的逻辑处理比如每个请求要查 API Key、要校验额度、要做用户维度的限流计数。这些操作背后是各种存储系统一旦下游推理集群出现性能退化HTTP 连接就会在网关节点的线程池里排队堆积连接数迅速把线程池打满CPU 飙升最终网关自己先失去响应。这就像一个高速公路收费站入口车道的通行能力本来设计好了但收费站前的等待队列一直排到城市主路上整个路网就瘫痪了。2.2 集群调度、排队与显存分配过了网关请求进入模型推理集群。这里通常会先经过一个调度器它要决定这个请求该路由到哪个模型副本、哪块 GPU、是否要排队等待还要做请求级别的优先级调度比如流式接口和普通接口的优先级就不同。大模型推理有个特点就是它不是无状态的单次计算而是需要把 KV Cache 部署在显存里显存的分配和释放非常频繁。当并发请求数超过集群的承载能力时调度器会选择把请求放到队列里等待而不是直接拒绝。这个“排队”机制本身没有错但问题在于如果队首的请求都是需要长时间生成的长文本请求排在后面的短请求就会经历不可接受的等待时间最终客户端超时断开但服务端还在默默生成浪费了算力还占着 KVCache。这就是典型的一笔“看不见的账”。2.3 推理引擎计算、显存带宽与 KV Cache真正执行生成任务的是推理引擎这里是大模型服务最复杂的战场。推理一个 token 有两个主要阶段Prefill 阶段把用户输入的 prompt 一次性处理完这个阶段是计算密集型GPU 利用率很高Decode 阶段则是一个 token 一个 token 地往外蹦每个 token 都要读取全部 KVCache这是一个高显存带宽消耗的操作GPU 算力反而用不满。当大量请求同时挤进来显存的分配会碎片化KVCache 的命中率下降原本应该被复用的显存块被迫反复申请和释放。更麻烦的是如果推理引擎做了抢占式调度新来的高优先级请求会打断正在生成的低优先级请求被抢走的请求恢复时还要重新读一遍前缀的 KV 信息GPU 的计算资源大量花在了重复计算上。这些细节单看一个不致命但叠加上超大规模并发就足以让整个推理集群的吞吐量跳水。2.4 基础设施层存储、日志与服务发现还有一个容易被忽略的环节基础设施依赖。日志服务、监控服务、配置中心、服务发现、对象存储所有这些辅助系统在故障时都会承受额外的压力。尤其是日志服务每个 token 的生成过程都会产生审计日志模型的输入输出要留存当流量异常增长时日志采集和写入的压力会同步暴增甚至反过来拖累主链路。很多服务号称“降级”了但实际上是降级的时候可能还要往日志服务里写入“我降级了”这条记录结果日志服务也堵住了。基础设施的故障是非常容易引发雪崩的因为主链路和辅助链路在资源上是互相竞争的并不是说辅助服务不重要恰恰是它们在关键时刻会成为压垮骆驼的最后一根稻草。3. 大规模模型服务的脆弱点这次事故暴露了什么3.1 算力池的弹性和超卖边界千问这类大规模模型服务背后是一个庞大的 GPU 集群但任何集群的算力都是有上限的。云服务商通常会按“安全水位”来规划容量比如只卖到总容量的 70% 到 80%多出来的部分作为弹性缓冲。但在真实场景里流量模型不是均匀的一个爆款应用上线、一次大面积宣传、甚至一个免费时段活动都可能瞬间把缓冲容量打穿。超卖更是一个微妙的话题。为了让 GPU 利用率最大化云服务商会在多个逻辑实例之间共享物理资源特别是通过多租户的方式把不同用户的小请求合并到大 batch 里推理。这种超卖在常态下效果很好但一旦某个大客户冲进来大量请求batch 被撑到巨大会直接导致同租户的其他请求延迟飙升隔离性就失去了意义最终所有用户一起体验“卡顿”。3.2 版本发布和配置变更的风险窗口另一个让我特别在意的细节是大模型服务的故障往往和发布窗口高度相关。模型版本升级、Prompt 模版调整、调度策略变更任何一个环节出了问题都可能引发非预期的行为。比如一个“加了一行模型回复格式要求”的改动可能让模型输出变长导致整体生成时间增加一倍平均延迟从 1 秒变成 2 秒所有下游超时设置全部被打穿。这不是说不能发布而是说大模型服务跟传统软件不一样传统软件的逻辑是确定性的测试过了就大概率没问题大模型的逻辑是概率性的同样的输入可能产生不同的输出长度、不同的 token 消耗。传统的自动化测试很难覆盖这种不确定性所以就要求发布策略要更加保守灰度范围要更小回滚速度要更快而且必须有完善的开关机制。3.3 依赖链故障一次故障引发的一连串问题大模型服务从来不是一个孤立的单体它依赖着无数外部服务用户体系、计费系统、内容安全审核、搜索增强、向量数据库、Redis 缓存、消息队列。其中任何一个服务出现性能瓶颈都可能反噬主链路。举个最典型的例子现在几乎所有模型服务都带内容安全过滤每次对话都要同步调用内容审核服务。如果审核服务的响应变慢那么整个对话请求就得一直挂着等它相当于被一个外围服务阻塞了主流程。此类“外部依赖导致主服务不可用”的问题在架构里非常常见但往往只在真正出故障的时候才被人想起来。3.4 “限流”失灵的技术根源理论上说大模型服务一定有完善的限流机制那为什么还是会崩关键在于限流本身需要依赖一个能感知全局状态的组件比如 Redis 里的计数器或者分布式令牌桶。而故障期间这个组件本身可能就是瓶颈或者说当流量继续增大时限流组件需要处理的请求数也变大了它的处理能力被占用导致限流判定变慢形成二次瓶颈。另一个尴尬的事实是很多限流策略只做“入口限流”比如限制每个 API Key 的 QPS。但当每个 API Key 的请求本身都是高并发持续请求时入口限流的粒度就太粗了它无法区分哪些请求是“重要的、需要保活的”哪些是“批量的、可丢弃的”。这就导致了一旦容量不够系统只能按先到先得的原则丢请求真正重要的付费用户可能和试用用户一起被拒之门外。4. 对 AI 应用开发者这不是偶发事故而是必修课4.1 调用层必须要考虑的“面向失败设计”这次“千问崩了”对我们这些做应用的人来说最直接的冲击就是不能把大模型 API 当成一个永远可用的黑盒。任何一个第三方依赖都可能故障而大模型 API 由于负载高、变量多故障概率其实比普通 HTTP 服务更高。所以所有调用大模型的服务在设计之初就必须做“面向失败”的架构就像十几年前我们设计 SOA 服务时一样。至少应该做好以下几件事超时设置不能依赖默认值必须按业务场景给模型调用明确设置 connect、read、write 三层超时重试必须带指数退避加抖动而且要考虑接口是否幂等大模型生成结果本身不幂等重试可能导致重复扣费或重复写入熔断必须有全局状态不能只靠单机失败计数至少要用 Redis 或类似组件做分布式熔断降级必须是多级的从“降级到别的模型”到“返回兜底文案”再到“提示用户稍后重试”每级都要有预案。4.2 多模型路由是刚需不是可选项这次事件之后应该有很多团队把“多模型路由”从远期规划提到了近期排期。道理很简单如果业务流量的主链路挂在某一个模型上那么这个模型的任何故障都会变成你的故障。引入多模型路由比如在千问故障时自动把流量切换到其他大模型甚至本地部署的私有化模型可以显著缩短故障影响时间。但这里要踩坑的细节很多。不同模型的返回格式不完全一样接口气候不同成本不同延迟特征不同这些都要有适配层。更关键的是同一个 prompt 在不同模型上的输出效果差异很大可能影响下游的结构化解析效果所以需要建立一个“模型路由表”根据任务类型、用户等级、实时错误率、价格约束等多个维度动态选择模型。这些都不难做但绝不能在故障发生后才开始做而是需要提前储备。4.3 业务侧的体验兜底怎么做技术层面做了再多用户看到的是“你的产品挂了”还是“AI 暂时繁忙”体验差别非常大。业务侧必须设计一个兜底交互流程当模型调用失败时不能直接抛异常而要给用户一个合理的解释和替代方案。比如可以在界面上提示“当前 AI 服务压力较大可稍后重试”或者先把用户的问题记录下来等模型恢复后异步补答还可以提供“转人工”的入口作为兜底。这里要注意兜底解决方案要经过完整的测试特别是在模型服务不可用的同时兜底方案本身不能依赖同一个故障源。如果你把兜底文案存在目标数据库里而模型服务的故障导致数据库也被打挂了兜底也就失效了。兜底逻辑要尽量轻量越底层越好。4.4 监控与告警要覆盖到“模型依赖”我见过太多团队的监控体系只覆盖到自家服务的 QPS、错误率、响应时间却没有覆盖到依赖的上游服务。这次千问故障里如果你没有对模型接口的错误率、延迟分位数、token 生成速率做监控那你的服务可能已经挂了半个小时了你还没发现直到用户投诉进来才后知后觉。正确的做法是针对模型调用单独建立一组监控指标包括但不限于调用成功率、平均延迟、P95/P99 延迟、token 生成速率、流式连接中断次数、超时重试次数。这些指标需要和业务指标做关联分析比如订单转化率下降是否是因为模型接口延迟升高了。对模型供应商的多个区域接入点也要分别监控防止某个区域的故障被平均值掩盖过去。5. 复盘之后真正值得带走的工程经验5.1 容量规划时记得把“不可压缩负载”算进去这次故障给我的一个很直接的提醒就是大模型服务的负载和传统 Web 服务有本质区别。传统服务吃 CPU 和内存我们可以通过水平扩容分担压力大模型服务吃的是 GPU 显存和显存带宽而且 GPU 资源的调度单位不是“请求”而是“请求的 token 数”。这意味着你没法靠单纯的加机器解决延迟问题因为每个模型的推理并发上限被物理显存死死卡着。所以在容量规划时不能只看 QPS更要看“平均输入 token 数”和“平均输出 token 数”以及它们的峰值。做应用的人虽然决定不了模型的容量但在设计业务时可以控制每次请求的输入长度、限制最大输出长度、设置合理的上下文轮数这些都能有效降低模型服务被压垮的概率。5.2 故障演练不能只演练“服务挂了”这一个剧本很多团队做过故障演练但剧本往往非常单一比如模拟某个服务进程崩溃、模拟数据库不可用。但大模型服务故障的剧本要丰富得多模拟上游模型接口延迟飙升到 10 秒、模拟流式接口生成到一半中断、模拟返回 200 但内容为空、模拟限流组件自身不可用。每一种“半坏”状态比彻底不可用更难以察觉也更需要做预案。演练的时候还要注意优先级别搞反了先保住登录、计费、订单等核心交易链路再考虑保住 AI 对话功能。AI 对话挂了用不了用户会不满但至少不会造成资损如果因为 AI 挂了导致订单重复创建、扣费异常那才是真正严重的生产事故。所以降级优先级的设计一定是从业务价值出发而不是从技术难度出发。5.3 建立“模型服务可用性”的内部知识库最后一个小建议可能跟纯技术关系不大但非常有价值。建议每个重度依赖大模型 API 的团队都维护一个“模型服务故障记录”的知识库把每次上游故障的时间、现象、排查过程、处理方案、客户沟通口径都记录沉淀下来。这次的“千问崩了”可以当作第一条记录后面每一次类似事件都往里补充。时间一长这个知识库就是你所在团队应对此类问题最宝贵的判断依据。我在处理这次故障的过程中最深的感受是依赖外部大模型服务的团队本质上是在跟一个黑盒打交道你既看不到它的内部状态也控制不了它的运维操作。那我们就只能用工程手段去对冲这种不确定性把故障对用户的影响降到最低。技术方案可能每家都不一样但这个思路应该是通用的。5.4 几个比较实用的参数配置参考很多同行问我那具体超时时间、重试次数这些参数到底怎么设置比较合适我给一个常规经验值大家可以根据自己的业务再做调整首次调用超时建议设置 30 到 60 秒因为大模型生成长文本确实需要时间尤其流式输出整个流持续几十秒很正常但要区分“连接建立超时”和“整体生成超时”连接一般 3 到 5 秒就该成功整体生成则要根据输出长度动态评估。重试次数建议不超过 3 次每次退避间隔先 1 秒、再翻倍、再翻倍并且加一点随机抖动防止所有客户端在同一个时间点重新发起请求。熔断阈值可以设置为错误率连续 30 秒超过 20%或者 P99 延迟超过预设值就打开熔断开关然后每 15 秒尝试放行一小部分流量探测恢复状态。这些数值没有绝对标准但有一个原则是确定的宁可牺牲一点体验也要先保证系统的整体稳定。比如你允许 3 次重试但如果第一次请求等了 50 秒才超时那么 3 次重试就是 150 秒过去了用户体验已经崩了。所以我的习惯是重试通常只用在“连接失败”这种快速失败场景生成中途断开的一次就好不重复尝试直接走降级方案。这次千问故障对很多团队是一次难得的“压力测试”虽然很痛但至少暴露了我们对上游依赖的风险认知还很不足。我希望大家在消化完这次故障之后不只是骂一句“连千问都能崩”而是真的回去把调用层、降级方案、监控告警、容量规划这几个模块都过一遍。下一次上游再出故障时你的系统能不能扛得住就看今天愿不愿意做这些看起来不紧急、但真正关键的工程了。