热路径与冷路径 AI:决定你 p99 延迟的架构决策
你发布的每一个 AI 功能,在成为产品决策之前,都首先是一个架构选择:这个模型调用是发生在用户的请求链路中,还是在用户无需等待的地方运行?这个选择通常由编写第一个原型的人做出,之后便不再被审视,并默默地决定了该功能在余下生命周期中的 p99 延迟。当事后分析(Post-mortem)询问为什么生产环境仪表盘在每周一上午 10 点变得无法使用时,答案几乎总是:某些本应属于冷路径(Cold-path)的东西被焊死在了热路径(Hot-path)中——而在 p50 时表现良好的模型,在流量扇出(Fan out)时,其 p99 的表现会变得极具灾难性。
热路径与冷路径的区别比 LLM 还要早。CQRS、流式架构、Lambda 架构——它们都在“必须立即响应”和“可以最终送达”之间划定了相同的界限。AI 工作负载的不同之处在于,走错方向的代价比以前高出了一个数量级。一个耗时 50 ms 的同步数据库查询变成 200 ms 是一次回归(Regression)。而一个在 p50 时耗时 1.2 秒的同步 LLM 调用在 p99 时变成 11 秒,则是你无意中做出的一项商业决策。
这篇文章旨在探讨如何有意识地做出这一决策。分为四个部分:将任何给定的 AI 交互置于热/冷光谱上的框架;冷任务渗入热路径的“饥饿”故障模式(Starvation failure mode);当流量或产品需求变化时跨越边界的迁移策略;以及在做出决定后让你保持诚实的监控手段。
究竟是什么决定了热或冷
这个框架由四个问题组成,请诚实地回答每一个交互:
- 用户感知的紧迫性。 用户是在盯着加载动画看,还是已经去做别的事了?聊天回复是热路径——让用户对着空白气泡等待 4 秒会摧毁体验。每周总结邮件是冷路径——没人会去计时。
- 可容忍的陈旧度。 如果答案延迟 30 秒,它还能发挥作用吗?搜索建议对陈旧度有很好的耐受性,因为用户会再次输入。结账时的反欺诈决策则完全不能容忍,因为交易是原子性的。
- 确定性要求。 热路径需要严格的输出格式契约。如果你的调用方需要严格的 JSON schema 进行下游路由,那么热路径中的 LLM 变数就是一个制造 Bug 的机器。冷路径则负担得起校验循环、拒绝并重试以及人工审核。
- 突发流量下的成本敏感度。 在 100 倍流量下,这个调用是否仍然需要每次都发生?冷路径可以在过载时丢弃。热路径则必须提供服务——即使是降级后的响应。
一个有用的洞察:只有当上述 四个 答案都指向热路径时,一个调用才是“热”的。如果任何一个维度可以容忍延迟,你就有其他选择。大多数团队 会跳过这一检查,并将所有内容都放入热路径,因为这样编写原型更容易。但这笔债会在几个月后到期,届时如果竞争对手发布了一个你的延迟预算无法负担的功能,代价就会显现。
一个具体的案例分析:开发工具中的 AI “解释此错误”功能。紧迫性很高——开发者被卡住了。陈旧度可以接受——错误是 5 分钟前记录的,用 500 ms 还是 3 秒来解释它不会改变诊断结果。确定性要求较低——输出是叙述性文本。突发流量下的成本敏感度中等。四个因素中有三个倾向于冷路径。因此,正确的架构可能是:立即发起解释请求,在 UI 中渲染骨架图(Skeleton),在结果到达时进行流式展示,并接受部分用户会在结果返回前切换标签页。这在传统的批处理意义上不是“冷路径”——它是热路径思维可能会遗漏的异步交互模式。
热路径饥饿模式
AI 架构中最昂贵的故障模式不是冷路径中的缓慢调用。而是冷路径的工作流在无人察觉的情况下泄露到了热路径中,然后拖垮了所有无关的用户请求。
它是这样发生的:功能的 1.0 版本有着清晰的分离:聊天响应同步通过一个小而快的模型,文档摘要则在批处理队列中每晚运行。一位产品经理要求“在用户打开文档时对其进行摘要”。工程师很自然地复用了聊天接口——因为它已经有了流式传输管道、身份验证和速率限制。一个季度后,聊天接口同时处理 2 KB 的聊天回合和 200 KB 的文档摘要。长摘要占用了 Worker 槽位。速率限制器充满了重量级请求。于是,与摘要毫无关系的聊天 p99 延迟开始攀升。
其机制是队列压力。LLM 网关和推理服务器从共享池中处理并发请求,当一个长尾请求到达时,它占据了一个短请求无法使用的槽位。混合工作负载中的尾部延迟由批处理中最长的请求决定,而不是中位数。vLLM 运维人员熟悉这种模式:当你监控 vllm:num_requests_waiting 时,你会先看到队列堆积,然后才看到延迟上升。当 p99 告警触发时,故障已经蔓延开来。
解决方案简单而明确:不要在同一个推理池中混合不同形态的工作负载。热路径流量拥有自己的专用池——为短请求设计,并配有激进的队列超时。冷路径流量则流向另一个针对吞吐量优化的独立池。即使两者后端使用相同的模型,你仍然需要两个独立的客户端池和两个独立的并发预算。这只需要几个小时的管道工程。其收益在于,相邻团队的产品决策不会吞噬你的延迟预算。
这个问题的组织架构版本更糟糕。如果一个共享基础设施团队拥有一个单一的 LLM 网关,而每个产品团队都将任何工作负载丢给它,该网关就会变成一场“嘈杂邻居”(Noisy-neighbor)的悲剧。通常的补救办法是为每个功能设置带优先队列的速率限制桶,但在一定规模下,真正的答案是一个将工作负载隔离视为产品(而非副业)的平台团队。
迁移手册:跨越边界
流量形态会发生变化。一个在面向 1,000 名测试用户发布时处于冷路径的功能,在面对 1,000,000 名用户时可能会变成热路径。一个在发布时处于热路径的功能,当你发现 80% 的请求可以容忍异步完成时,可能需要将其移至冷路 径。迁移总是比从零构建(Greenfield build)更难,因为它发生在生产环境中。
一个真正有效的迁移方案如下:
- 对当前状态进行检测 (Instrument)。 在移动任何东西之前,记录该功能现有状态下的 p50/p95/p99 延迟、单用户成本、缓存命中率以及用户流失率。这些数字是决定迁移是否成功的对比基准。
- 在同步调用的同时引入异步包装器。 先不要切换默认行为。构建冷路径执行逻辑——通常是基于 Temporal、Inngest 或自建队列的持久化工作流——并让其将结果生成到 UI 可以轮询或订阅的存储中。现有的同步路径继续运行。
- 双写并对比。 针对一部分采样流量,同时调用两条路径。最初会丢弃异步路径的结果;你只是想确认它能产生等效的输出,并且基础设施在真实流量下不会崩溃。这一步能发现那些意外情况:顺序问题、幂等性 Bug,以及仅在真实并发下才会出现的超时。
- 按切片切换流量。 将一小部分群体(通常先是内部用户,然后是 1% 的用户,再到 10%)路由到异步路径。不仅要观察延迟仪表盘,还要观察流失率和支持工单。如果 UX 的变化令用户反感(例如加载动画被换成了他们会关掉的横幅),你会在追踪链路 (Traces) 显示异常之前,先在下游转化指标中看到它。
- 带有紧急开关 (Kill switch) 的停用。 在至少一个完整的事故周期内,将同步路径保留在功能开关 (Flag) 之后。冷路径基础设施会引入新的失败模式——队列积压、消费者滞后、毒信丸 (Poison-message) 风暴。紧急开关是在你诊断问题时,让你回到已知良好状态的紧急制动器。
反向迁移——将某些内容从冷路径移至热路径——较为少 见,但值得一提。触发因素通常是产品团队发现该功能在即时响应时效果更好。反向迁移比正向迁移更容易,因为你是在缩小状态空间,但陷阱在于冷路径模型可能是为了适配批处理输出而设计的。一个要求 “返回结果的 JSON 数组” 的 Prompt 在冷处理中运行良好,但当用户正在字符接字符地等待该数组流式传输时,会造成痛苦的 UI 体验。请为新路径重新设计 Prompt;不要假设旧的 Prompt 具有通用性。
告诉你迁移是否成功的监控指标
热/冷路径的放置不是你在代码审查中验证的决定,而是在生产遥测中验证的。以下四个指标能真正告诉你架构是否稳固:
- 热路径 p99 与功能发布率解耦。 如果每个新功能的发布都是通过在请求路径中增加一个同步模型调用来实现的,那么你的热路径 p99 就是产品团队开发速度的函数。这是错误的耦合。一个架构良好的热路径应该有一个由基础设施强制执行的延迟预算,而不是由 PM 协商出来的。
- 冷路径完成时间的百分位数。 对于异步工作,从请求入队到结果可用的 p99 完成时间是预测用户满意度的指标。如果 p50 是 3 秒,而 p99 是 180 秒,那么你面临的是队列饥饿问题,而不是平均值问题。
- 按延迟分段的流失率。 这是没人追踪但人人都该追踪的指标。对于响应时间的每 500 毫秒分段,有多少比例的用户放弃了交互?断崖式下跌点几乎从不在团队预想的地方。关于热/冷边界的产品决策应该依据这条曲线做出,而不是凭直觉。
- 每跳重试率 (Retry rate per hop)。 链式 Agent 工作流中每增加一跳,尾部延迟就会成倍增加。一个 3 步工作流,如果每步有 5% 的重试率,边际上会多消耗约 16% 的 Token;而 7 步工作流则接近 35%。如果你的冷路径因为重试放大而默默消耗了两倍于你建模时的计算资源,那么你的单位成本就是虚假的。
这些指标共同作用,将热/冷决策从一次性的架构判定转变为系统的一种可观察属性。如果团队稍后跨越边界迁移某些内容,同样的仪表盘会告诉你这次迁移是带来了提升还是引入了退化。
前瞻性的启示
下一波 Agent 框架正在通过让持久化工作流变得像函数调用一样廉价,从而消除热路径和冷路径在操作上的区别。这是好事——像 Temporal、Inngest、DBOS 和 Cloudflare Workflows 这样的持久化执行平台消除了大部分让异步 AI 工作流变得痛苦的样板代码,它们让 “挂起并恢复” 变得足够廉价,以至于 “等待用户确认 10 秒后继续” 不再是一个庞大的基础设施项目。但它们并没有消除架构决策。它们只是让决策更容易 实现,而不是更容易 做对。
系统的持久化部分不适合放置用户正在等待的工作。而同步部分也不适合放置除此之外的任何内容。内化这一框架,对边界进行检测,你的 p99 就不再是听天由命的事。
未来几年胜出的 AI 功能不会是那些拥有最佳 Prompt 或最华丽模型的。它们将是那些架构师在第一时间就仔细划分了热/冷界限的功能— —并且在流量形态改变时,有纪律地重新划分。
- https://blog.langchain.com/how-do-i-speed-up-my-agent/
- https://agentnativedev.medium.com/the-p99-problem-designing-llm-inference-for-real-users-11deb35bb8d4
- https://martinfowler.com/bliki/CQRS.html
- https://learn.microsoft.com/en-us/azure/architecture/patterns/cqrs
- https://temporal.io/solutions/ai
- https://www.inngest.com/blog/durable-execution-key-to-harnessing-ai-agents
- https://render.com/articles/durable-workflow-platforms-ai-agents-llm-workloads
- https://www.dbos.dev/blog/durable-execution-crashproof-ai-agents
- https://blog.cloudflare.com/workflows-v2/
- https://docs.anyscale.com/llm/serving/benchmarking/metrics
- https://particula.tech/blog/fix-slow-llm-latency-production-apps
