第 16 章 LLM服务架构Triton
第 16 章 服务架构
第 16 章 服务架构
学习目标
- 掌握主流模型服务器:Triton、TorchServe、KServe、Ray Serve、Seldon;
- 理解 API 网关、负载均衡、限流、鉴权的职责;
- 理解自动扩缩容:HPA、KEDA、自定义指标;
- 理解缓存、队列、背压、超时、重试的可靠性原语;
- 掌握灰度、蓝绿、金丝雀发布与 A/B 测试、影子流量、多臂老虎机。
16.1 模型服务器:推理引擎的工程外壳
第 14 章的推理引擎(vLLM/TensorRT-LLM)解决「算得快」;模型服务器(Model Server)在它外面套上「多模型管理、动态批处理、版本切换、指标暴露」的工程外壳。
| 服务器 | 定位 | 特点 |
|---|---|---|
| Triton(NVIDIA) | 通用高性能推理 | 多框架、动态批处理、多模型并发、GPU 利用率标杆 |
| TorchServe | PyTorch 官方 | 与 PyTorch 生态一体、模型打包 |
| KServe | K8s 原生 | 与 K8s 深度集成、自动扩缩、Serverless |
| Ray Serve | 弹性 Python 服务 | 编排灵活、与 Ray 生态一体、多模型/多版本 |
| Seldon | K8s 模型部署 | 灰度、多框架、监控集成 |
选型逻辑:GPU 极致性能用 Triton;K8s 平台一体化用 KServe;Python 编排与多模型灵活路由用 Ray Serve;PyTorch 单模型快速上线用 TorchServe。LLM 场景常见组合是 vLLM(引擎)+ KServe/Ray Serve(平台)。
# Ray Serve 快速暴露一个 LLM 服务(多模型路由示例)
from ray import serve
from transformers import pipeline
@serve.deployment
class LLM:
def __init__(self, model_id):
self.pipe = pipeline("text-generation", model=model_id)
async def __call__(self, request):
return self.pipe(request.query["prompt"])[0]["generated_text"]
serve.run(LLM.bind("Qwen/Qwen2-7B"))16.2 API 网关、负载均衡、限流、鉴权
服务前面还有一层网关(Gateway),四个职责:
- 鉴权(AuthN/AuthZ):API Key / OAuth / 租户鉴权。LLM 场景还有内容鉴权(提示注入、敏感内容拦截,第 23 章);
- 负载均衡:把请求分发到推理副本。LLM 特有的坑:KV Cache 与并发不均——均衡要考虑每实例的当前负载(显存余量、排队长度),而非简单的轮询;
- 限流(Rate Limit):按 token 或请求数限制,防打爆与防滥用。LLM 的限流粒度是 token/min + 并发数(不只请求数);
- 路由(第 15 章)+ 可观测性埋点(第 21 章)。
# 网关限流示例(token 粒度)
limits:
- key: "api_key"
actions: [{ "type": "request-count", "limit": 1000, "window": "1h" }]
# LLM 场景再加 token 总量限制
- key: "api_key"
actions: [{ "type": "token-count", "limit": 1_000_000, "window": "1h" }]16.3 自动扩缩容:HPA、KEDA、自定义指标
在线服务的容量要跟着负载走:
- HPA(Horizontal Pod Autoscaler):K8s 原生,按 CPU/内存扩缩。对 LLM 是「错误的信号」——推理是 memory-bound(第 14 章),CPU 利用率不能反映真实瓶颈;
- KEDA(Kubernetes Event-driven Autoscaling):按事件驱动(队列长度、请求数)扩缩,比 HPA 更适合;
- 自定义指标:按 GPU 利用率 / KV 余量 / 排队长度 / 吞吐 扩缩——LLM 服务的正确信号。
%%{init: {"themeVariables": {"primaryTextColor": "#000000", "textColor": "#000000", "labelColor": "#000000", "nodeTextColor": "#000000", "labelTextColor": "#000000", "scaleLabelColor": "#000000"}}}%%
flowchart LR
A[GPU 利用率/排队长度] -->|指标| B[KEDA 触发]
B -->|扩容| C[新增推理副本]
B -->|缩容| D[回收空闲副本]
C --> E[负载均衡重新分配]扩缩容的致命陷阱:LLM 模型加载慢(7B 权重加载 30s+,70B 分钟级)——扩容要「预热」(提前加载模型、提前分配 KV 资源),否则流量尖峰来了副本还没就绪。这就是「Serverless 不适合大模型」的根源之一(第 18 章展开)。
16.4 缓存、队列、背压、超时、重试
服务的可靠性五个原语:
- 缓存:LLM 场景的缓存分三层——前缀缓存(第 14 章,KV 复用)、语义缓存(相同/相似问题的答案缓存)、结果缓存(确定性请求)。语义缓存用 embedding 相似度命中,能大幅省成本但要注意时效性;
- 队列:削峰填谷。在线服务队列要短(背压),离线服务队列可深(第 15 章);
- 背压(Backpressure):下游处理不过来时,上游要「慢下来」而非无限堆积。HTTP 层体现为限流 + 503;队列层体现为拒绝或降级;
- 超时(Timeout):LLM 的生成时长波动大(长输出慢),超时设置要在「容忍长输出」与「防止拖死」间权衡——通常用「首 token 超时 + 每 token 空闲超时」双阈值;
- 重试(Retry):网络抖动重试(指数退避 + 抖动);但对确定性模型输出要小心幂等性;重试会放大下游压力,要限制重试次数。
# LLM 服务调用的超时与重试(指数退避)
def call_with_retry(fn, max_retries=3, base_delay=0.5):
for attempt in range(max_retries):
try:
return fn(timeout=30) # 30s 总超时
except TimeoutError:
if attempt == max_retries - 1: raise
time.sleep(base_delay * (2 ** attempt) + random.uniform(0, 0.2))16.5 发布策略:灰度、蓝绿、金丝雀
模型发布与代码发布不同——新模型可能更差(离线指标好不等于在线好,第 9 章)。因此发布必须渐进:
| 策略 | 做法 | 优点 | 缺点 |
|---|---|---|---|
| 滚动发布 | 逐个替换实例 | 简单 | 出问题影响面渐进但难隔离 |
| 蓝绿 | 新旧两套环境,一键切 | 回滚极快 | 双倍资源 |
| 金丝雀 | 新模型只接小流量 | 风险最小、可灰度观察 | 观察周期长 |
| A/B 测试 | 随机分流量比业务指标 | 统计可信 | 需实验设计 |
%%{init: {"themeVariables": {"primaryTextColor": "#000000", "textColor": "#000000", "labelColor": "#000000", "nodeTextColor": "#000000", "labelTextColor": "#000000", "scaleLabelColor": "#000000"}}}%%
flowchart LR
A[新模型 v2] -->|5% 流量| B[金丝雀观察
延迟/质量/业务]
B -->|达标| C[50% 流量]
C -->|达标| D[全量]
B -->|异常| E[回滚到 v1]
C -->|异常| E影子流量(Shadow Traffic):新模型接收线上真实请求的「副本」,只推理不返回用户,用来在零风险下观察新模型在生产流量上的表现(不占用户结果)。多臂老虎机(MAB):自动根据实时反馈动态分配流量给表现更好的模型,是 A/B 的自动化演进。
16.6 LLM 发布的特殊注意点
- Prompt 与模型强耦合:新模型可能需要新 Prompt 模板(第 17 章 Prompt 版本化)——灰度时新旧 Prompt 要一起管;
- 评估先于发布:第 9 章的在线评估(影子 + 小流量)是发布门禁;
- 回滚 = 换权重,但 KV/缓存要同步:语义缓存、前缀缓存带模型版本标签,避免新模型命中旧缓存;
- 成本突变:新模型可能更长/更贵,灰度期间要盯 token 成本(第 17、21 章)。
本章要点回顾
- 模型服务器是推理引擎的工程外壳;Triton 性能标杆、KServe K8s 原生、Ray Serve 编排灵活。
- 网关四职责:鉴权、负载均衡(按负载非轮询)、限流(token 粒度)、路由。
- 扩缩容信号要用 GPU/排队长度,不是 CPU;LLM 扩容要预热,Serverless 对 70B 不友好。
- 可靠性五原语:缓存(三层)、队列、背压、超时(双阈值)、重试(限次)。
- 发布必须渐进:金丝雀最小风险;影子流量零风险观察;MAB 是自动化 A/B。
- LLM 发布的独特点:Prompt 耦合、缓存带版本、盯成本。
习题
- 你的服务在流量尖峰时扩容,但新副本 2 分钟内不可用(模型加载慢)。设计预热方案。
- 为什么 LLM 用「首 token 超时 + 每 token 空闲超时」而不是单一总超时?
- 设计一个金丝雀发布流程:流量比例、观察指标、自动回滚条件、与语义缓存的协调。
- 语义缓存的命中会引入「模型版本不一致」风险,如何设计缓存键与版本策略?
延伸阅读
- NVIDIA Triton Inference Server 文档
- KServe / Seldon 官方文档
- Ray Serve 文档
- Kubernetes HPA / KEDA 文档
- 各云厂商模型网关(API Gateway for LLM)白皮书
下一章预告
第 17 章 LLM 服务专题:Prefill/Decode/KV 管理的服务化、多租户隔离与配额、Token 成本与 GPU 利用率、RAG/Agent/工具调用服务、流式与结构化输出。