Skip to content

模型推理服务 架构模板

代表产品 / 原型:vLLM、SGLang、NVIDIA Triton、HuggingFace TGI、Ray Serve 一句话定位:在 GPU 上把大模型跑起来对外提供服务,靠连续批处理、KV 缓存分页等手段,把昂贵的 GPU 算力榨到最高吞吐、最低延迟。


1. 一句话定位

模型推理服务 = 一台围着 GPU 转的「吞吐榨取机」。它的全部使命就一句话:把 GPU 喂饱、用满、用省。

它其实是 AI 对话产品模板 里那个「推理服务」组件的放大特写。当你不满足于调别人的 API、要自己跑开源 / 私有模型时,你面对的就是这台机器:输入是「模型权重 + 一堆 prompt」,输出是「源源不断的 token」,而中间最难的事,是让一块几万块的 GPU 一刻都别空转

2. 业务本质:它在解决什么问题

它把「一个训练好的模型文件」变成「一个能扛并发、低延迟、高吞吐的在线服务」。

为什么它值得单独成一类系统? 因为它的成本结构极端反常:

普通服务「多一个请求几乎不要钱」;推理服务每生成一个 token 都在烧 GPU 时间。GPU 又贵又缺,所以「单位 GPU 每秒能生成多少 token」直接等于毛利率。整套架构就是围绕这个数字做优化。

3. 核心需求与约束

功能性需求:

  • [ ] 加载模型权重到显存
  • [ ] 接收请求、批处理推理、流式逐 token 输出
  • [ ] KV 缓存管理(自回归生成的中间状态)
  • [ ] 多副本 / 多模型服务
  • [ ] (可选)量化、前缀缓存、多卡并行

非功能性需求 / 质量属性:

质量属性目标为什么对这类系统重要
吞吐(tokens/s/GPU)越高越好直接决定单卡服务人数和成本
首字延迟 TTFT< 1s用户等第一个字的时间
单 token 延迟 TPOT低且稳决定「读起来流不流畅」
GPU 利用率拉满空转就是烧钱
显存效率越省越好显存是硬上限,省下来能服务更多人

关键约束(不可逾越的边界):

  • 🔴 GPU 贵且缺:头号约束,一切为它的利用率服务。
  • 🔴 推理是有状态的自回归:生成第 N 个 token 依赖前面所有 token 的中间结果(KV cache),这块狂吃显存
  • 🔴 显存是硬上限:KV 缓存 + 权重塞满显存后,就服务不了更多并发了。
  • 🔴 吞吐与延迟天然矛盾:batch 越大吞吐越高,但单请求延迟也越高。

4. 架构全景图

   多个请求(长短不一)
   ▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────────────┐
│  调度器(Scheduler)—— 灵魂所在                                  │
│  • 请求排队                                                    │
│  • 【连续批处理】:每一步动态组批,完成的请求立刻出批、           │
│     新请求立刻进批,不让 GPU 等"最慢的那个"                      │
└───────────────────────────┬─────────────────────────────────┘

┌─────────────────────────────────────────────────────────────┐
│  GPU 执行引擎                                                  │
│  ┌───────────────┐   ┌─────────────────────────────────┐    │
│  │ 模型权重(显存) │   │  KV 缓存(分页管理,像 OS 虚拟内存) │    │
│  └───────────────┘   └─────────────────────────────────┘    │
│         每一步算出一批 token ──▶ 逐 token 流式吐回             │
└───────────────────────────┬─────────────────────────────────┘
                            ▼  模型权重启动时从对象存储加载进显存
                  ◀══ 流式返回 token ══

灵魂部件是调度器:它决定了 GPU 是「满负荷连轴转」还是「等一个人写完大家干等」。连续批处理把后者变成前者,这一个决定能让吞吐翻好几倍。

5. 组件职责

  • 调度器(Scheduler):管理请求队列,每个生成步都动态重组批次(continuous batching)。为什么需要:这是 GPU 利用率的总开关——见决策 1。
  • KV 缓存管理:为每个在途请求管理它的 KV cache,用分页(PagedAttention)避免显存碎片。为什么需要:KV 缓存吃显存且大小动态变化,粗放分配会浪费大量显存——见决策 2。
  • GPU 执行引擎:真正跑模型前向计算、采样出 token。为什么需要:核心算力所在。
  • 权重加载:把几十~上千 GB 的模型文件从对象存储加载进显存。为什么需要:模型太大,启动时一次性载入。
  • (可选)前缀缓存:复用相同前缀(如系统提示)已经算过的 KV。为什么需要:省掉重复计算,和 prompt 缓存同源。
  • 路由 / 多副本:把请求分发到多个 GPU 副本。为什么需要:单卡撑不住时水平扩。

6. 关键数据流

场景一:连续批处理(这台机器最核心的魔法)

传统【静态批处理】:
  攒齐 8 个请求 → 一起算 → 必须等最慢(生成最长)的那个写完 → 整批才结束
  ✗ 短请求早就算完了,却被迫陪着空等 → GPU 大量空转

【连续批处理】:
  每生成一步,就检查:谁写完了?→ 立刻请它出批、把新请求填进来
  ✓ GPU 每一步都在满负荷干活,没有"陪等" → 吞吐翻数倍

场景二:一次流式生成

1. 请求入队 ──▶ 调度器把它编入当前批次
2. 为它在 KV 缓存里分配分页块(prefill 阶段:处理输入 prompt)
3. 逐步生成(decode 阶段):每步算出下一个 token ──▶ 立刻流式吐回
4. 命中 EOS 或达到上限 ──▶ 该请求出批,释放它的 KV 缓存页给别人用

7. 数据模型与存储选择(本质是显存布局)

这类系统的「数据」主要活在显存里,而不是数据库。

数据放在哪为什么
模型权重对象存储 → 加载进显存大、不可变、启动时载入
KV 缓存显存(分页块)自回归生成的中间态,极吃显存,要精细管理
请求 / 批次状态内存高频、易失、随请求生灭
前缀缓存显存 / 内存复用热点前缀的计算结果

教学点:推理服务的「存储难题」不在磁盘,而在显存——怎么在有限显存里塞下尽可能多的并发请求的 KV 缓存,是它和普通系统最不一样的地方。

8. 关键架构决策与权衡 ⭐

决策 1:静态批处理,还是连续批处理?(吞吐的总开关)⭐

  • 静态批处理:攒一批一起算、一起结束。简单,但短请求被长请求拖着空等,GPU 利用率低。
  • 连续批处理:每步动态进出批。
  • 取向:必选连续批处理。代价是调度复杂,但 GPU 利用率和吞吐的提升是数量级的。

决策 2:KV 缓存——连续分配还是分页?⭐

  • 给每个请求预留一大块连续显存:简单,但请求长度不确定,会产生大量显存碎片和浪费。
  • 分页(PagedAttention):像操作系统管虚拟内存那样,把 KV 缓存切成小块按需分配。
  • 取向:分页。它借用了 OS 的成熟智慧,大幅提升显存利用率、支持更高并发。

决策 3:吞吐 vs 延迟,怎么平衡?

  • 大 batch:吞吐高,但单请求延迟(尤其尾延迟 P99)被拉高。
  • 小 batch:延迟低,但 GPU 没喂饱、吞吐低、成本高。
  • 取向:按业务定调——离线批量任务偏大 batch 求吞吐;在线交互偏小 batch 求延迟;高级做法是把 prefill 和 decode 阶段分离调度。

决策 4:自建推理,还是直接调 API?(MVP 最该想清楚的)⭐

  • 调供应商 API:零运维、按量付费,起步最快。
  • 自建:用开源 / 私有模型、数据自留、规模大后单 token 更便宜,但要养 GPU 和这套复杂系统。
  • 取向:先调 API(经 AI 网关),等到「量大到自建更划算」或「必须私有 / 定制模型」时,再自建。

9. 规模化与瓶颈

  • 第一个瓶颈:单卡吞吐。 → 破解:连续批处理 + 分页 KV + 前缀缓存,把单卡榨干。
  • 第二个瓶颈:模型太大,单卡放不下。 → 破解:多卡并行(张量并行 / 流水线并行),把一个模型切到多张卡上。
  • 第三个瓶颈:请求量超过单副本。 → 破解:多副本 + 负载均衡,水平扩。
  • 第四个瓶颈:长上下文吃爆显存。 → 破解:分页 KV、量化、上下文压缩。
  • GPU 扩容慢且贵:不像加 Web 服务器那样秒扩,容量规划要提前。

10. 安全与合规要点

  • 多租户隔离:共享 GPU 的不同租户之间,显存 / 请求要隔离,防数据串味。
  • 输入限制:超长输入会撑爆显存,可被用来做 DoS,要限制长度。
  • 模型权重保护:私有 / 自研模型权重是核心资产,访问要受控。
  • 资源配额:防止单用户占满 GPU 拖垮所有人。

11. 常见误区 / 反模式

  • 用静态批处理 → ✅ 连续批处理,别让 GPU 陪等。
  • KV 缓存连续大块分配 → ✅ 分页管理,消除显存碎片。
  • 每个请求单独跑(batch=1) → ✅ 组批,否则 GPU 严重空转、成本爆炸。
  • 盲目追求超大 batch → ✅ 平衡吞吐与尾延迟。
  • MVP 就自建 GPU 集群 → ✅ 先调 API,量到了再自建。

12. 演进路线:MVP → 成长期 → 成熟期(不同阶段怎么设置)

阶段规模量级怎么设置(具体)此时该操心什么
MVP验证想法别自建! 直接调模型供应商 API(经 AI 网关)。非要本地 / 私有模型时,单卡用 vLLM / TGI 起一个实例先验证产品,别一上来烧 GPU
成长期自建上规模自部署 vLLM / SGLang:开连续批处理 + 分页 KV + 前缀缓存;量化省显存;多副本 + 负载均衡把单卡吞吐和单 token 成本压到最优
成熟期大模型 / 高并发多卡并行跑大模型、prefill/decode 分离调度、多区域 GPU 池、模型路由(大小模型混用)、自动扩缩容成本、容量规划、容灾、质量与延迟的平衡

13. 可复用要点

  • 💡 先认清系统真正的「稀缺资源」,围绕它的利用率做架构。 这里是 GPU,所以一切为「别让 GPU 空转」服务——和 AI 对话产品 同一条心法。
  • 💡 批处理是吞吐的杠杆。 把多个请求合并计算,是从数据库到 GPU 都通用的提效手段。
  • 💡 善于从其它领域借成熟智慧。 PagedAttention 直接搬了操作系统「虚拟内存分页」来治 KV 缓存碎片——好架构常常是「旧思想用在新问题上」。
  • 💡 缓存重算代价高的东西。 前缀缓存复用已算的 KV,等同于 prompt 缓存,是省钱的通用招式。
  • 💡 「自建 vs 购买」先算规模账。 没到规模就自建重型基础设施,是典型的过度设计。

🎯 随堂检验

🤔把 GPU 利用率拉满、大幅提升吞吐的关键是?
  • A静态批处理:攒一批一起算、一起结束
  • B连续批处理:每步动态进出批,不让 GPU 陪等
  • C每个请求严格单独处理

参考原型与延伸阅读

本模板基于以下真实开源项目论文的架构理念整理。这几个项目就是当今 LLM 推理服务的事实标准,直接读它们最可靠。

🔧 开源原型(可直接读代码):

📖 论文 / 文档:


📌 一句话记住模型推理服务:它不是「把模型跑起来」那么简单,而是「一台围着昂贵 GPU 转、靠连续批处理和显存分页把算力榨到极致的精密机器」——所有设计都在回答『怎么让每一块 GPU 每一秒都在满负荷生成 token』。