Agent 如何支撑 3 万 QPS:从单实例到分布式推理的工程全景

agent高级
AI Engineer Roadmap2026年08月09日

普通接口支撑 3 万 QPS 只需要一堆无状态节点,而 Agent 支撑 3 万 QPS,本质上是在为一个「每请求会调用 3~10 次 LLM 推理」的系统做容量工程。


一、先把账算清楚:3 万 QPS 意味着什么

在动手设计架构之前,必须先回答一个问题:Agent 的 QPS 和普通 API 的 QPS 根本不是同一个量纲。

一个典型的 ReAct 风格 Agent,处理一次用户请求通常要经历:

用户Query → 意图路由 → 规划(LLM) → 工具调用 → 观察整理(LLM) → 检索(向量库) → 总结(LLM) → 输出

假设一次用户请求平均触发 3 次 LLM 推理调用,每次推理平均生成 500 个 token,那么:

指标计算数值
用户侧 QPS需求30,000
LLM 侧推理 QPS30,000 × 390,000
输出 token/秒90,000 × 50045,000,000
输出 token/分钟45,000,000 × 6027 亿
单卡输出能力以 H100 实测约 4,000~6,000 tok/s 计~5,000 tok/s
推理卡需求量45,000,000 ÷ 5,0009,000 张

这就是 Agent 高并发的第一性矛盾: 我们以为在解决「请求调度」问题,实际上是在解决「GPU 算力」问题。3 万 QPS 的 Agent 系统,即使按最激进的推理优化,也需要千卡级别的推理集群。任何不谈算力的 QPS 方案都是空中楼阁。

因此,支撑 3 万 QPS 的工程主线只有一条:想尽一切办法降低「每次用户请求消耗的推理 token」,同时让每一张 GPU 的单位时间产出最大化。


二、容量建模:先做预算,再谈架构

2.1 从业务指标反推资源

容量规划必须从业务侧开始,逐层反推:

业务目标:3 万 QPS 用户请求
  → 每请求平均 LLM 调用次数 N(目标:从 5 压到 2.5)
  → 每调用平均输入 token(目标:从 8K 压到 3K)
  → 每调用平均输出 token(目标:从 800 压到 400)
  → 得出总 token 吞吐 = QPS × N × (input + output)

这三组数字(N、输入长度、输出长度)就是 Agent 高并发的三个可优化的自由变量,比堆 GPU 重要得多。工程上的所有手段,最终都是围绕它们做文章:

  • 减少 N:合并多步推理(见 4.2)、缓存整条执行链
  • 减少输入:上下文剪枝、前缀缓存、检索 top-k 收敛
  • 减少输出:输出格式约束、更小的规划粒度、强制结构化输出

2.2 延迟与并发的互斥关系

容量建模还必须同时考虑延迟约束。假设产品要求 P95 延迟 3 秒,单次 LLM 调用平均耗时 1 秒,那么:

  • 串行 3 次调用需要 3 秒 → 不允许任何额外的排队时间;
  • 这意味着推理集群的利用率不能超过 60%~70%,必须预留缓冲,否则队列时延会瞬间击穿 P95 目标。

结论: 支撑 3 万 QPS 的同时满足延迟约束,实际需要的算力是「纯吞吐计算值」的 1.3~1.5 倍。容量预算里必须显式预留这 30%。


三、推理服务层:吞吐的胜负手

Agent 的推理请求有很强的结构性,可以针对性地优化。

3.1 请求特征与优化空间

Agent 推理请求特征对推理的影响优化手段
输入远大于输出(上下文 5K~30K,输出几百 token)前缀计算占绝对主导Prefix Caching / KV Cache 复用
同一个 Prompt 模板高频复用大量重复计算模板级前缀缓存、按模板预填充
请求到达具有突发性队列抖动、GPU 利用率低Continuous Batching + 动态批大小
单次 Agent 循环中多次调用相似上下文上下文重叠跨请求 KV Cache 共享

3.2 核心引擎选型:Continuous Batching

传统静态批处理(Static Batching)以「批」为单位整体等待,批内最慢的请求拖累整批,GPU 利用率极低。Continuous Batching(连续批处理,vLLM 首创并普及)按 token 粒度调度:某个序列生成完就立刻让出槽位,新请求随时插入。同一时刻一个 GPU 上可以混合执行处于不同阶段(预填充/解码)的多个请求。

工程上直接选择成熟方案,不要自研:

  • vLLM:生态最成熟,PagedAttention + Continuous Batching,支持 Prefix Caching 与多种量化
  • TensorRT-LLM:NVIDIA 官方,推理性能上限最高,但工程复杂度高
  • SGLang:RadixAttention 前缀缓存非常契合 Agent 的模板化请求

3.3 Prefix Caching:Agent 场景的「复利」

Agent 请求中,系统提示词、工具描述、Few-shot 示例往往占输入的大半,且跨请求高度重复。Prefix Caching(vLLM 的 --enable-prefix-caching)让相同前缀的 KV 不再重复计算:

  • 命中时,预填充阶段从毫秒级计算变为纯内存拷贝;
  • 在 Agent 场景,输入 token 的成本通常可下降 40%~70%。

更进一步的思路是按 Agent 类型拆分前缀:

/cache/v1/planner-prompt      → 规划 Agent 的公共前缀(KB 级,长期复用)
/cache/v1/retriever-prompt    → 检索 Agent 的公共前缀
/cache/v1/qa-prompt           → 问答 Agent 的公共前缀

对高频 Agent 模板,甚至可以预填充:服务启动时预先计算公共前缀的 KV,请求到达时直接拼接用户部分,把首 token 时间再压一个数量级。

3.4 模型与服务拆分:大小模型分层

不要让所有请求都走最大的模型。按请求难度分层路由:

  • 路由/意图识别:7B14B 小模型(12 张卡即可支撑上万 QPS 的纯分类任务)
  • 规划/工具选择:14B~32B 中模型
  • 最终生成/复杂推理:70B+ 大模型,仅对需要深度推理的请求启用

配合投机解码(Speculative Decoding):小模型草稿 + 大模型验证,在输出 token 上通常可获得 1.5~2.5 倍加速,且不损失精度。


四、Agent 运行时层:让「会话」可以水平扩展

4.1 无状态化:Agent 的十二要素

LLM 推理天然无状态,但 Agent 有状态——执行栈、工具结果、历史消息都在运行内存里。要让 Agent 水平扩展到几千个副本,必须把状态外置:

Agent 实例(无状态,可随时销毁重建)
   ├── Session 状态  → Redis Cluster(TTL 管理,如 10 分钟无操作回收)
   ├── KV Cache 状态 → 推理服务内部(Prefix Cache,跨请求复用)
   ├── 工具调用结果   → 结果缓存(带失效策略)
   └── 任务队列       → Kafka / Redis Stream(削峰 + 背压)

设计约束:

  • 每次请求幂等:Agent 步骤必须支持「重试即重放」,不能因为实例重启丢上下文;
  • 状态 TTL 化:所有会话状态必须有生命周期,否则内存和 Redis 会持续膨胀;
  • 工具调用纯函数化:写操作(下单、发消息)与读操作分离,重试只对读操作生效。

4.2 减少调用次数:把串行循环改成并行 DAG

3 万 QPS 下,每减少一次 LLM 调用,就是减少几千张卡的负载。典型的优化:

串行(4 次 LLM 调用):

规划 → 检索 → 读文档 → 总结

并行 DAG(2 次 LLM 调用 + 并行工具):

规划(产出工具清单)→ [检索 ‖ 读文档 ‖ 查天气] 并行 → 汇总生成

LangGraph / 自研状态机都支持并行分支,代价是编排复杂度,收益是LLM 调用次数直接减半。此外还有更激进的方案:

  • 执行链缓存:对「相同意图 + 相同参数」的请求,缓存整条 Agent 执行结果(不只是 LLM 输出);
  • 计划复用:同一类任务(如「查天气」「查订单」)的规划结果高度相似,规划步骤命中模板时直接跳过 LLM。

五、缓存体系:在 LLM 之前的四道防线

高并发系统里,缓存的目标是让流量尽量不触达最贵的组件。Agent 系统的缓存分层如下:

层级缓存内容命中率期望说明
L1 响应缓存完整 Agent 执行结果10%~30%相同问题的重复请求,直接返回
L2 语义缓存相似问题的结果复用5%~15%向量化相似度匹配(如 >0.95 判定重复)
L3 规划缓存任务规划步骤20%~40%相同任务模板跳过规划 LLM
L4 工具缓存工具调用结果30%~60%检索结果、API 返回按 key 缓存
L5 前缀缓存KV Cache40%~70%推理层内部,见 3.3

执行顺序: 请求到达 → L1/L2 命中直接返回(不产生任何推理成本)→ L3 命中跳过规划 → L4 命中跳过工具 → L5 命中降低推理计算量。

一个容易被忽略的细节:语义缓存必须和新鲜度策略配合。股票行情、天气这类时效性数据不能命中缓存;可以用「TTL 按数据类别区分」+「缓存键包含时间窗口」来解决。


六、流量治理与弹性伸缩

6.1 入口与背压

3 万 QPS 的流量不可能均匀到达。入口层必须做:

  • 网关限流:令牌桶 + 按用户/按 Agent 类型分级配额,超限返回 429 而非把压力传导给推理集群;
  • 队列削峰:突发流量进入 Kafka / Redis Stream,消费者按推理集群的实际吞吐拉取,实现天然背压;
  • 流式返回:SSE 流式输出让首字节时间(TTFB)大幅下降,用户感知的「响应」远早于完整生成。

6.2 弹性伸缩策略

推理集群的扩容不是即时的(拉起一个带权重加载的推理实例需要几十秒到几分钟),所以:

  • K8s HPA 基于自定义指标(排队长度、GPU 利用率、token 吞吐),而非 CPU;
  • 预留缓冲池:常备 10%~20% 的 warm 实例应对突发;
  • 推理实例按模型类型分池:小模型池、大模型池独立伸缩,避免互相挤占;
  • 降级预案:峰值超过容量的 120% 时,自动将请求降级到小模型 + 缓存命中模式,保证核心链路可用。

七、可观测性:3 万 QPS 下的容量会计

高并发系统最怕「黑盒」。Agent 场景建议建立以下指标,缺一不可:

业务层:用户QPS、按Agent类型QPS、P50/P95/P99 端到端延迟、缓存命中率
执行层:每请求LLM调用次数、每请求token消耗、工具调用耗时
推理层:TTFT、ITL(token间延迟)、GPU利用率、队列深度、KV Cache命中率
成本层:每百万token成本、每请求成本、按Agent类型的成本分布

重点追踪两个成本杠杆指标:

  1. 平均每用户请求的 LLM 调用次数 N——这是成本优化的总抓手,任何架构调整都应以 N 的下降为目标;
  2. 每请求平均输入 token——它与 Prefix Cache 命中率直接相关,是推理集群负载的先行指标。

八、落地路线图:分四步走

支撑 3 万 QPS 不是一次重构能完成的,建议按以下节奏推进:

第一步(0→1 万 QPS):

  • 无状态化 Agent + Redis 会话存储
  • vLLM 推理集群 + Continuous Batching + Prefix Caching
  • 网关限流 + SSE 流式输出
  • 大小模型分层路由

第二步(1 万→2 万 QPS):

  • 响应缓存 + 语义缓存 + 工具缓存
  • Agent 执行链并行化(串行改 DAG)
  • 意图模板化,规划步骤缓存

第三步(2 万→3 万 QPS):

  • 推理集群精细调优(投机解码、量化、张量并行/流水并行合理配比)
  • 前缀缓存精细化(按 Agent 模板预填充)
  • 队列削峰 + 弹性伸缩 + 降级预案
  • 全链路追踪(OpenTelemetry)与成本看板

第四步(持续):

  • 每一轮优化都以「每请求 token 消耗」为北极星指标
  • 定期用压测验证:3 万 QPS 下 P95 延迟是否守住,GPU 利用率是否达到 70%+

九、关键结论

  • 3 万 QPS 的本质是 token 吞吐问题,不是请求调度问题;先算清「每请求消耗多少 token」,再决定买多少卡。
  • 推理层用成熟引擎(vLLM/SGLang/TensorRT-LLM),把精力留给 Prefix Caching 和批处理调优,绝不自研推理内核。
  • 状态外置是无状态化的前提,无状态化是水平扩展的前提;会话状态必须 TTL 化、步骤必须幂等。
  • 缓存是成本最大的杠杆:五级缓存体系 + 执行链缓存,能让真实的 LLM 负载比 QPS 数值低一个数量级。
  • 用「每请求 LLM 调用次数」和「每请求输入 token」两个指标管理容量,它们比 GPU 数量更能反映系统健康度。

支撑 3 万 QPS 的 Agent 系统,最终拼的不是某一次优化,而是把「少算、快算、缓存、复用」贯穿到每一层架构决策中。