Skip to content

十二、工程化与部署运维

这一章检验 LLM 应用有没有真正"上过量"。架构、成本、延迟、监控、发布,每一题都对应一次真实的线上考验,面试官想听的是带数字、带取舍的实战经验。

119. 画一个高并发 LLM 应用的架构:网关、限流、队列、模型服务、缓存分别放在哪?怎么扩容?

必刷 · 中等

参考答案

文字版架构,从外到内分层描述:

  1. 接入层:WAF / CDN → 负载均衡 → API 网关。职责:认证、租户识别、请求校验、路由、SSE 流式透传(反代必须关缓冲)。无状态,直接水平扩。
  2. 限流层(挂在网关):多维度令牌桶/滑动窗口——用户级 QPS + 并发槽位数(LLM 请求是长连接慢请求,只限 QPS 不够,必须限制"同时在生成的请求数");租户级配额;全局兜底限流。限流状态放 Redis,网关实例无状态。
  3. 预处理层:输入内容安全初审、Prompt 组装、缓存查询。
  4. 缓存层:精确缓存(请求前缀/全文哈希 → Redis)在前,语义缓存(向量相似度命中)在后,命中直接返回,省掉整个下游。
  5. 队列层(模型服务之前):核心削峰组件。LLM 请求秒级到几十秒延迟,突发流量超过推理能力时排队而不是打死服务;按优先级分队列(付费/免费、交互/后台任务分流),配合等待时长估算和超时礼貌拒绝。
  6. 模型服务层:两条路线——自建推理集群(vLLM 等引擎 + K8s GPU 节点,实例内部用 Continuous Batching 做调度)或外部 API(经模型网关管理上游配额与多厂商容灾,见 Q124)。长请求和短请求分池部署,避免一个长文分析堵死一批快问答(队头阻塞)。
  7. 旁路与异步:输出内容审核可异步复核;日志、trace、计费入消息队列异步消费,不阻塞主链路。

扩容策略

  • 无状态层(网关、预处理、缓存)常规水平扩;
  • 模型服务是真正瓶颈:自建路线先压测出单实例吞吐(见 Q123),按峰值并发 / 单实例并发槽数算实例数,再加 20~30% 冗余;GPU 扩容要分钟级,必须按流量时间曲线提前扩,缩容要慢(防抖动),扩缩信号用队列长度和排队时间而非 CPU;
  • 外部 API 路线提前申请配额,配多厂商备份;
  • 降级链路:高峰先限流新请求保在途请求 → 再降输出上限、关重功能 → 路由到小模型或缓存兜底。

一个常见误区:把 CRUD 时代的架构照搬过来。LLM 请求耗时长、GPU 资源贵、流量不均匀,这三点决定了并发槽管理 + 队列削峰 + 提前扩容是整套架构的中心,而不是数据库和连接池。

面试官可能追问

  • SSE 流式场景下网关和链路要额外注意什么?(关缓冲、读超时大于最长生成时间、断连时要向上游取消请求止损 Token)
  • 用户请求在队列里排了 30 秒,体验怎么保?(返回排队位置与预估等待时间,超时给重试建议或降级到缓存/小模型)
  • 怎么判断该自建还是调 API?(按 QPS × 平均 Token 数估月成本对比 GPU TCO,叠加合规约束,参考第一章模型选型题)

120. LLM API 的限流、重试、降级策略怎么设计?指数退避和抖动了解吗?

高频 · 中等

参考答案

限流:客户端要维护并发槽(信号量)+ QPS 双重限制;对 429 响应读 Retry-After 头做服务端指示的退避;多 Key 轮转池可平滑单 Key 限额,但要看厂商条款是否允许。

重试:只重试瞬时且幂等的错误——429、5xx、网络超时;不盲重:400(参数错、超上下文,重试无用)、内容审核拒绝(重试还是拒)、流式已输出一半的失败(要考虑幂等和体验)。重试要设上限(2~4 次)和总预算,防止重试风暴放大负载。

指数退避 + 抖动

  • 退避间隔按指数增长:1s → 2s → 4s → 8s,设上限(如 30~60s),给上游恢复留时间;
  • 抖动(jitter)必须加:一批请求同时失败后,若都按固定间隔重试,会在同一时刻集体再撞一次,形成周期性尖峰反复冲击上游(惊群),可能把一次抖动拖成雪崩;抖动给每个客户端的重试时间加随机量,把尖峰摊平;
  • 典型实现:sleep = min(cap, base × 2^n) × random(0.5, 1.5)
  • 配合熔断器:连续失败超阈值就熔断,流量走降级,冷却后半开试探恢复。

降级:主模型不可用 → 备用模型(提前做过 Prompt 兼容性验证,见第十二章迁移题)→ 再降为缓存相似问答、模板回复、排队稍后通知;核心业务常备一条低延迟小模型通道。对非核心业务,直接拒绝新请求保护在途请求,也是一种降级。

落地建议:用成熟的库或网关能力集中配置重试与熔断策略,别散落在各业务代码里各自为政。

面试官可能追问

  • 为什么抖动是必需项而不是优化项?(同步重试造成周期性负载尖峰,是级联故障的经典成因)
  • 流式请求中断在半路,重试会怎样?(已消耗的 Token 不退,重试等于双倍计费——要么容忍重来,要么记录半截结果让用户选择继续)

121. 怎么降低 Token 成本?说说精确缓存 / 语义缓存、Prompt 压缩、小模型路由等手段。

高频 · 中等

参考答案

按投入产出比排序:

  1. Prompt 瘦身(先做):审计 system prompt 和 few-shot,删冗余示例;system prompt 从 3000 Token 瘦到 1200,所有请求直接受益,零风险;
  2. 精确缓存:分两类——厂商 Prompt Caching / Context Caching:固定前缀(system prompt、长文档、few-shot)命中后输入按缓存价计费,约为正常输入价的十分之一量级(各厂商不同),要求前缀完全一致且稳定,所以固定内容放前、变量放后;自建精确缓存:请求完全相同直接返回缓存结果,适合模板类、重复请求;
  3. 语义缓存:query 向量化后与历史问答比对,相似度超阈值(经验值 0.95 左右)即返回缓存,命中省整次调用。风险是误命中("怎么取消订单"和"取消不了订单"向量很近但答案相反),只用于 FAQ、闲聊等容错场景,命中率做到 20~40% 已很可观;
  4. 小模型路由:入口先分类或规则判断,简单请求(格式化、常规问答)走便宜的小模型,难的升级旗舰。多数业务 60~80% 流量可被小模型接住,综合成本能降一半以上;路由层本身要便宜且快,误路由的代价是质量事故;
  5. Prompt 压缩:历史对话滚动摘要、检索片段先 rerank 再砍 top-k、用 LLMLingua 类工具压缩冗余 Token。代价:压缩本身有一次额外调用,且可能丢关键信息——上下文很长(如超 8K)才划算,短上下文反而负优化;
  6. 输出控制:限制回答长度、结构化输出去掉开场白和总结段、用 stop 序列提前截断;
  7. 批处理:离线任务走 Batch API,约五折换小时级延迟。

落地节奏:先做 1+2(无脑赚),再上 3+4(要设计),最后抠 5+6;同时建成本看板(单请求平均成本、分模型分场景),否则优化无法度量。

面试官可能追问

  • Prompt 缓存为什么经常不命中?(前缀里混入了时间戳、用户名等变量,任何一字之差都从头算——审计前缀模板的稳定性)
  • 语义缓存的阈值怎么定?(用标注的相似问对跑 ROC,按业务误伤容忍度选,宁可少命中不可错返回)

122. 大模型的响应延迟怎么优化?首 Token 延迟(TTFT)和整体吞吐分别怎么压?

中频 · 中等

参考答案

先分清指标:用户体感主要看 TTFT(首字出现即感知"开始回答了")和单请求总时延;系统容量看吞吐(tokens/s、QPS)。两者优化路径不同甚至冲突——小 batch 延迟低、大 batch 吞吐高,要按场景取舍。

TTFT 优化

  • 压缩输入:prefill 计算量与输入长度成正比,砍历史、砍检索片段、瘦身 system prompt 是第一杠杆;
  • Prompt 缓存:固定前缀跳过重复 prefill,TTFT 显著下降;
  • 流式输出:不加速生成本身,但把体感延迟从总时长变成 TTFT,感知收益最大;
  • 模型与部署:换小模型、量化版本;自部署调 chunked prefill 防长请求饿死短请求;选就近 region、独享通道降网络 RTT;
  • 投机解码:小模型起草、大模型并行验证,decode 阶段加速 2~3 倍(需自建部署,见第九章推理题)。

吞吐优化

  • Continuous Batching:逐步动态插入/移出请求,消除静态批的补齐浪费,吞吐提升数倍是常态;
  • PagedAttention:KV Cache 分页管理,减少碎片、提高并发 batch;
  • 量化(INT8/INT4):decode 是访存瓶颈,权重变小直接提速;
  • 长短请求分池、多实例负载均衡、超大模型张量并行;
  • 排队治理:排队时间常占总延迟大头,扩容和优先级调度比调模型更有效。

方法论:先把 P50/P95 延迟分段拆解(网络 → 审核 → 检索 → 排队 → prefill → decode),找到大头再对症下药;排队占 60% 时去调模型参数是无效优化。

面试官可能追问

  • 为什么 decode 阶段快不起来?(每步只出一个 Token、反复读权重和 KV Cache,算力吃不饱;靠 batching 摊薄访存)
  • TTFT 和吞吐都要时怎么权衡?(分场景:聊天类小 batch 保延迟,后台批任务大 batch 保吞吐,用队列优先级隔离两类流量)

123. 私有化部署一个开源模型,从选型、量化、压测到上线要做哪些事?

中频 · 中等

参考答案

按四个阶段推进:

选型

  • 按任务难度定尺寸:抽取、分类、常规问答 7B~14B 级够用,复杂推理 32B~70B 级起步;
  • 候选模型(Qwen、DeepSeek、LLaMA 系等)用自己的评估集跑分(100~300 条业务真实样本 + bad case),不信公开榜单——榜单与业务表现相关性有限;
  • 确认 license 允许商用。

量化与部署

  • 显存估算:FP16 权重约等于参数量 × 2 GB,再加 KV Cache 和激活值;7B FP16 约 14~16GB 显存,单张 24GB 卡可跑;70B 级量化后也要多卡;
  • 量化取舍:INT8(AWQ/GPTQ)近乎无损;INT4 更省但复杂推理任务会有可感知下降——量化后必须重跑评估集验证,不能拍脑袋;
  • 推理引擎按生态和吞吐需求选 vLLM / SGLang / TensorRT-LLM,确认支持 continuous batching 和长上下文。

压测(最容易偷懒的一步):

  • 真实流量分布压:输入输出长度、突发模式都要像线上,而不是等长的合成请求;
  • 核心指标:单实例并发槽数、TTFT、每 Token 间隔(TPOT)、tokens/s、P95 延迟、显存峰值、失败率;
  • 专门压长输入长输出的边界场景——KV Cache 随长度膨胀,最容易在这里 OOM;
  • 由单实例容量推实例数(峰值流量 + 冗余),扩容信号选排队长度。

上线

  • K8s + GPU Operator 编排,健康检查、监控告警(Q125)先行;
  • 发布走评估集回归 + 小流量灰度(Q126),模型文件版本化、可一键回滚;
  • 合规侧:对外的生成服务完成内容审核与备案义务。

常见坑:只测单请求效果不测并发吞吐;上线后没有回滚预案;长上下文场景没压 KV Cache 峰值导致高峰 OOM。

面试官可能追问

  • INT4 量化精度掉多少?(任务相关:分类抽取几乎无损,复杂推理可能掉几个点,必须以自己评估集实测为准)
  • 单机多卡和多机多卡怎么选?(优先单机多卡(张量并行),跨机通信延迟和运维复杂度高,只在单机放不下时用多机)

124. 统一接入多家模型的模型网关怎么设计?路由、故障转移、配额、密钥管理怎么做?

中频 · 较难

参考答案

定位:模型网关是业务方访问所有模型的统一出口,屏蔽厂商差异,集中管路由、成本和安全四件事。

统一接入层

  • 对内暴露一套规范 API(事实标准是 OpenAI 风格的 chat/completions 接口),内部适配各厂商的参数名、流式格式、错误码;
  • 横切能力全部下沉到网关:重试与熔断(Q120)、Token 计量、trace 日志(Q118)、敏感数据扫描(Q114)、Prompt 缓存——业务方零感知。

路由引擎

  • 业务侧用抽象模型名(如 chat-fast / chat-smart),网关映射到具体厂商模型,升级换供应商不动业务代码;
  • 路由维度:场景路由(分类走小模型、难任务走旗舰)、成本路由(效果达标的候选里选单价低的)、合规路由(含敏感数据的请求只路由到备案通过的通道)、灰度路由(新模型小流量试用);
  • 规则放配置中心,支持热更新,每次路由决策落日志可审计。

故障转移

  • 主动健康探测 + 错误率/延迟熔断:单通道异常自动切备用;
  • 分级降级:同模型多 Key → 同级备模型 → 低级模型 → 模板兜底;
  • 关键约束:主备模型要预先做兼容性验证——换模型不是零成本,Prompt 行为差异可能导致质量下降,备选对要在评估集上过回归,明确已知的降级损失。

配额与成本

  • 按租户/应用/模型维度限 QPS、并发、日 Token 上限,超限拒绝或降级;
  • 实时 Token 计量(请求前估算、响应后按 usage 校准),成本分摊到租户,预算告警;
  • Key 池化:多 Key 轮转平滑单 Key 限流,Key 级健康状态管理。

密钥管理

  • 密钥全放 KMS 或 Vault 类密钥管理服务,配置和代码里无明文;
  • 网关是唯一持钥方,业务方用内部签发的 token 调网关;Key 轮换对业务无感;所有密钥访问留审计日志。

可以自研,也可以基于开源网关(LiteLLM、One API 等)二次开发;多模型是长期状态的话,这层值得第一天就建。

面试官可能追问

  • 成本路由怎么验证"效果达标"?(定期用评估集切片给候选模型打分,结合报价动态调整路由权重)
  • 流式请求怎么做故障转移?(只在建连阶段切换;输出到一半出错,切换意味着用户看到断稿重来,一般选择重生成并告知,而不是无缝切换)

125. LLM 应用的监控告警看哪些指标?(延迟、错误率、Token 用量、拒绝率、人工接管率等)

中频 · 中等

参考答案

指标按"系统 → 质量 → 成本 → 用户"四类组织:

系统健康

  • 延迟:TTFT、总时延的 P50/P95/P99,且分段统计(排队、检索、prefill、decode、工具调用),否则定位不了慢在哪;
  • 错误率:分类统计——API 错误、超时、审核拦截、格式校验失败、工具执行失败,各自含义不同;
  • 饱和度:队列长度、并发槽占用率、自建侧的 GPU 利用率与显存。

质量健康(LLM 应用特有,也是最容易漏的):

  • 拒绝率:回答"不知道/无法回答"的占比,突增通常意味着知识库覆盖或检索出了问题;
  • 人工接管率:客服等场景的核心逆指标,直接反映 AI 解决率;
  • 审核拦截率:突增可能是注入攻击或被用户找到绕过姿势;
  • 缓存命中率与路由分布:异常波动关联成本和效果;
  • 抽样质量分:LLM as Judge 自动打分 + 人工抽检校准的离线/准在线指标。

成本

  • 单请求 Token 消耗(输入/输出分开)、单请求成本、日总成本、分模型分场景拆分;
  • Prompt 长度分布:均值持续上涨多半是历史累积或检索注入失控。

用户侧

  • 点踩率、投诉量、用户对答案的编辑幅度、会话完成率、转人工前轮次。

告警设计要点

  • 绝对值 + 变化率组合(质量指标绝对值意义有限,环比突增 2 倍才是信号);
  • 排队时间单独告警——这是最领先的扩容信号,早于延迟恶化;
  • 成本预算告警(日额度 80% 预警);
  • 多指标共振才升级页面:接管率、投诉率、拒绝率同时涨,大概率是真实质量事故。

工具:指标和 trace 用 OpenTelemetry 标准接入,LLM 专项视图用 Langfuse / LangSmith 类平台,重点看每次调用的 prompt、成本和链路。

面试官可能追问

  • 没有标注数据怎么在线监控质量?(用代理指标:用户反馈、接管率、编辑率,再加周期性抽样跑 LLM 评估)
  • 哪个指标最先反映"模型变差"?(投诉率和接管率——用户用脚投票的指标最诚实)

126. 灰度发布和新模型上线流程怎么做?怎么快速发现"新模型反而变差了"?

中频 · 较难

参考答案

完整流程分四段:上线前验证 → 流量灰度 → 快速劣化检测 → 可回滚

上线前(离线)

  • 评估集回归:新模型跑全量业务评估集(含近期线上 bad case),对比旧模型——重点看分场景分数而非只看总分,总分持平但某场景掉 5 个点很常见也更危险;
  • Prompt 兼容性:新模型对格式指令、system prompt 的遵循习惯不同,需要适配的先改 Prompt 并在评估集上验证(模型 + Prompt 绑定为一个发布单元,否则没法归因);
  • 边界与安全测试:安全对齐、注入抗性、超长输入、格式稳定性压测;
  • 成本与延迟重估:分词器不同导致 Token 消耗变化,输出风格影响长度和延迟。

灰度放量

  • 按 1% → 5% → 25% → 50% → 100% 阶梯放量,每档观察至少覆盖一个完整时段(不同时段用户群不同);
  • 按用户哈希分流而非按请求随机——同一用户始终在同一组,保证体验一致、指标不被污染;
  • 设对照组做同时段对比,抵消时间因素。

快速发现"变差"(核心)

  • 用户代理指标:投诉率、点踩率、人工接管率、答案编辑幅度、会话完成率;
  • 系统代理指标:格式校验失败率(新模型不守旧格式的第一信号)、输出长度分布漂移、安全拦截率、重试率;
  • 自动护栏:预设阈值(如投诉率相对对照组 +50%),触发即自动暂停放量甚至回滚,不等人工发现;
  • 灰度期间两组输出持续抽样,用 LLM as Judge 盲评对比,显著劣化即告警。

回滚

  • 模型路由配置版本化,一键切回;Prompt 若同步改过则一起回滚;
  • 保留灰度期数据做事后归因,沉淀进评估集。

关键心态:新模型上线是假设检验,不是升级——榜单提升不等于业务指标提升,只有灰度数据说了算。

面试官可能追问

  • 灰度期太短,质量问题滞后暴露怎么办?(加影子流量:新模型并行处理线上请求但不返回给用户,只用于离线对比,多花一份成本换安全)
  • 灰度期间用户反馈能定位到组吗?(会话和分组标记全链路透传,反馈天然带组别属性,方便归因)

127. 长时间运行的 Agent 任务怎么做持久化和断点恢复?

低频 · 较难

参考答案

核心问题:Agent 任务跑几十分钟、上百步,中途崩溃(服务重启、上游超时、OOM)后必须能从断点续跑而不是从头再来——既是成本问题(Token 已花掉),也是体验问题(让用户再等 20 分钟不可接受)。

持久化什么(checkpoint 内容)

  • 完整状态而非消息列表:消息历史只是之一,还要有执行计划与当前进度、中间产物(摘要、检索结果、生成的文件引用)、工具调用记录、重试计数;
  • 状态设计成显式数据结构(可序列化的 dict / ORM 对象),而不是散落在各步变量里——这是能做 checkpoint 的前提;
  • 幂等标识:每步(每次工具调用)有唯一步骤 ID 和幂等键,恢复时先查"这步是否已执行、结果是什么"。

何时持久化

  • 每步执行后落一次(一次 LLM 调用、一次工具执行各算一步);粒度权衡:太细写入开销大,太粗故障后重放代价高;
  • 非幂等操作的顺序:先写意图日志,执行成功后更新状态(写前日志思路)——防止"执行了但没记录"(崩溃后重复执行,付款付两次)或"记录了但没执行"(任务漏步骤)。

怎么恢复

  • 加载最近 checkpoint → 重建上下文(历史消息塞回 prompt,过长则摘要 + 近期轮次)→ 从未完成步骤继续;
  • 工具幂等分级:查询类直接重跑;副作用类先查下游实况(那笔付款是否已创建)再决定跳过或补偿,绝不盲目重试;
  • 单步失败独立重试与降级,超过阈值转人工处理,不拖垮整个任务。

工程落地:LangGraph 的 checkpointer 提供开箱的 state 快照与线程恢复;自建可用 Redis(热状态)+ 关系库(持久)双层,天级长任务直接落库。另一个关键设计:计算与状态分离——推理实例无状态、随时可杀可扩,任务状态全在外部存储,这是长任务 Agent 能上 K8s 弹性调度的前提。

面试官可能追问

  • checkpoint 损坏或版本不兼容怎么恢复?(快照带版本号,加载失败回退上一个快照重放,最坏标记任务失败并保留产物转人工)
  • 几百步之后上下文远超窗口怎么办?(分层摘要 + 中间产物外置存储按 ID 引用,需要时再取回,参考第七章上下文管理)

128. Serverless GPU 和常驻服务怎么选?冷启动问题怎么缓解?

低频 · 中等

参考答案

选型逻辑是利用率 × 延迟敏感度的矩阵:

维度Serverless GPU常驻服务
流量形态突发、间歇、日均利用率低持续高负载、平稳
延迟要求能容忍秒到几十秒冷启动TTFT 要求严格
成本模型按用量计费,零闲置成本固定支出,打满才划算
运维负担低,免集群管理高,容量规划和监控全自理

经验判断:日均利用率低于约两三成、流量毛刺大 → Serverless;平稳高负载 → 常驻(盈亏平衡点随厂商定价浮动,要按自己的流量曲线算总账,Serverless 单价常更高)。混合形态最常见:常驻池保底 + Serverless 弹性扛峰值;测试环境天然适合 Serverless。另一个关键差异:Serverless 通常绑定厂商运行时,推理引擎、量化方式、定制算子的自由度远低于自管集群。

冷启动缓解(大模型冷启动 = 拉镜像 + 加载权重 + 预热,可达几十秒到分钟级,远慢于 CPU 服务):

  1. 保活:用厂商的预留并发/保活实例,或定时心跳流量防止缩到零——但保活实例就是钱,本质变成半常驻,要按流量曲线算保活几个最划算;
  2. 缩小冷启动单元:模型加载占大头——选小模型、量化权重(文件小加载快);镜像预拉取到节点、权重缓存到节点本地盘,减少拉取时间;
  3. 预热调度:按时间曲线提前扩容(早高峰前预热),缩容设长冷却期(流量归零后等 10~20 分钟再释放);
  4. 请求侧兜底:冷请求路由到常驻池的双层架构,或排队 + 明确的等待反馈;
  5. 提高单实例复用:实例起来后用 continuous batching 多槽位承接,减少再次触发扩容。

同理适用于常驻服务的自动扩缩:GPU 实例扩容本身就要分钟级(加载权重),提前扩、延迟缩是通用原则。

面试官可能追问

  • 具体怎么算划不划算?(用真实流量曲线分别模拟两种模式的月成本:常驻 = 实例数 × 单价,Serverless = 调用量 × 单价 + 保活费,交叉点即决策点)
  • 为什么 GPU 冷启动远慢于 CPU?(多 GB 权重加载、CUDA 初始化、推理引擎预热编译,不只是起进程的时间)

Released under the CC-BY-SA-4.0 license.