云计算百科
云计算领域专业知识百科平台

【推理引擎】大模型推理服务部署、性能调优与生产实践:SGLang、vLLM、TensorRT-LLM

【推理引擎】大模型推理服务部署、性能调优与生产实践:SGLang、vLLM、TensorRT-LLM

文章目录

  • 【推理引擎】大模型推理服务部署、性能调优与生产实践:SGLang、vLLM、TensorRT-LLM
    • 一、推理引擎:选型与运行原理(SGLang、vLLM、TensorRT-LLM)
      • 1. 推理引擎解决什么问题
      • 2. 三种引擎的关键执行路径
      • 3. 前缀缓存与 KV Cache
    • 二、模型部署:环境准备、服务部署与 API 调用
      • 1. 环境与版本检查
      • 2. SGLang Docker 单机部署
      • 3. vLLM Docker 部署
      • 4. TensorRT-LLM Engine 构建与服务
      • 5. Kubernetes 部署骨架(以 SGLang 为例)
      • 6. 从网关访问推理服务
      • 7. OpenAI 兼容 API 调用
      • 8. 采样参数如何影响结果
      • 9. 使用引擎原生前端
    • 三、性能调优:从显存到吞吐(指标、量化与 PD 分离)
      • 1. 先建立正确的性能指标
      • 2. 显存预算与上下文长度
      • 3. Tensor Parallel、Data Parallel 与副本
      • 4. 调度和前缀缓存调优
      • 5. PD 分离:把 Prefill 与 Decode 拆成独立服务池
      • 6. 与 PD 分离配套的进阶优化
      • 7. 量化、FlashInfer 与 Kernel 选择
    • 四、生产实践:生产治理、监控与排障
      • 1. 监控和日志
      • 2. 告警和弹性策略
      • 3. 发布、升级与安全边界
      • 4. 常见故障排查
      • 5. 常见问答
      • 6. 一份上线检查清单
    • 五、平台化演进:多模型、多租户、容量与成本治理
      • 1. 多模型注册与智能路由
      • 2. 多租户隔离、配额与公平调度
      • 3. 容量规划与单位 Token 成本
      • 4. 异构 GPU、Engine 兼容与多地域容灾
      • 5. 从单服务到推理平台的演进路线

把一个大模型跑起来,只能证明模型能推理;把它作为线上服务稳定地提供给多个调用方,还要解决显存、并发、流式输出、模型加载、监控和故障恢复等问题。

SGLang、vLLM 和 TensorRT-LLM 都是面向大语言模型和多模态模型的推理引擎。它们通常提供 OpenAI 兼容接口,也会在请求调度、KV Cache、批处理、量化和 GPU Kernel 等层面做优化。推理引擎的核心价值不是“把模型包一层 HTTP”,而是把模型权重、请求队列和 GPU 执行组织成可持续优化的运行时。

本文以 Qwen、Llama 等 Hugging Face 格式模型为例,说明 SGLang、vLLM 和 TensorRT-LLM 的定位差异、部署方式、关键参数和生产排障路径。命令中的版本、模型名和 GPU 数量需要按实际环境替换,生产环境应固定推理引擎、CUDA、驱动和模型 revision,而不是直接使用 latest。

在这里插入图片描述

一、推理引擎:选型与运行原理(SGLang、vLLM、TensorRT-LLM)

1. 推理引擎解决什么问题

一个推理请求通常经历以下阶段:读取聊天消息、分词、构造 KV Cache、调度批次、执行 Prefill、逐 Token Decode、采样并返回结果。并发一高,真正的瓶颈往往不是模型前向本身,而是请求排队、显存碎片、重复计算和不同长度请求之间的相互阻塞。

三种引擎都将这些通用能力放入 runtime,并在其上提供在线 API 或编程入口:

入口作用适用场景
OpenAI 兼容 API 通过 /v1/chat/completions、/v1/completions 提供在线推理 接入现有 SDK、网关和业务服务
引擎原生 API 用 SGLang Python 前端、vLLM Python API 或 TensorRT-LLM Runtime 编排推理 Agent、离线批处理、复杂生成逻辑

三种引擎的优化侧重点并不完全相同:

对比项SGLangvLLMTensorRT-LLM
服务接口 OpenAI 兼容 API + Python 前端 OpenAI 兼容 API + Python API TensorRT-LLM Runtime + trtllm-serve 等服务入口
核心优化 RadixAttention 前缀缓存、连续批处理、结构化生成 PagedAttention、连续批处理、广泛模型适配 TensorRT-LLM Engine、融合 Kernel、量化和 CUDA Graph
典型优势 多轮对话、重复前缀和结构化生成 通用在线服务、生态成熟、上手快 NVIDIA GPU 上追求极致吞吐和低延迟
主要代价 版本变化快,需要验证模型适配 特定模型和场景未必达到最优 Engine 构建、版本绑定和部署复杂度更高
选型建议 用真实业务压测 TTFT、TPOT、缓存命中率和成本 用真实业务压测吞吐、P99 和运维成本 用目标 GPU、目标精度和固定模型构建后再比较

这里的比较不是为了证明哪个框架“绝对更快”。模型架构、输入长度、输出长度、并发度、GPU 型号和量化方式都会改变结果。

2. 三种引擎的关键执行路径

客户端 / AI Gateway
│ OpenAI API 或引擎原生请求

SGLang / vLLM / TensorRT-LLM Server
├─ 请求解析、鉴权边界和参数校验
├─ Tokenizer 与 Prefill 调度
├─ Prefix Cache 或 Paged KV Cache 查询
├─ Continuous Batching 动态组批
├─ GPU Worker 执行 Prefill 与 Decode
└─ SSE 流式返回 Token

├─ /health、/metrics、运行日志
└─ Prometheus、Grafana、日志平台

Prefill 负责一次性处理输入上下文,计算量大,主要影响首 Token 延迟(TTFT);Decode 按 Token 迭代生成,主要影响每 Token 延迟(TPOT)和输出吞吐。SGLang 更强调 RadixAttention 前缀复用,vLLM 以 PagedAttention 管理 KV Cache,TensorRT-LLM 则依赖构建好的 Engine、融合 Kernel 和 CUDA Graph。把长上下文请求和短请求混在一起时,三种引擎都需要在吞吐与交互延迟之间做取舍。

3. 前缀缓存与 KV Cache

多轮对话、系统提示词和批量文档问答经常共享一段前缀。如果每次请求都从头计算,GPU 会重复执行相同的 Prefill。SGLang 的 RadixAttention 会将已计算的 Token 前缀组织成可复用的树结构;vLLM 也支持 Prefix Caching,但实现和参数名称随版本变化;TensorRT-LLM 则通常结合 KV Cache 管理、Paged Context FMHA 和 CUDA Graph 等能力优化执行。

前缀缓存能否生效,取决于输入 Token 是否真的相同:系统提示词的空格、工具描述的排序、消息序列化方式和模板版本发生变化,都会导致缓存未命中。因此应固定 Chat Template,把稳定内容放在前面,把用户动态内容放在后面,并在指标中观察命中率,而不是只凭感觉判断。

缓存不是无限的。推理引擎会在显存预算内管理 KV Cache,缓存过多会挤压模型权重和新请求空间。生产环境需要同时关注缓存命中率、KV Cache 使用率、请求排队时间和 OOM 次数。不要把 SGLang 的缓存参数直接照搬到 vLLM 或 TensorRT-LLM,应以实际版本的启动帮助和指标为准。

二、模型部署:环境准备、服务部署与 API 调用

本章按照模型服务从准备到可调用的顺序展开:先校验运行环境,再分别启动三种推理引擎,最后通过统一 API 和网关完成验证。

1. 环境与版本检查

上线前先记录以下信息,后续排障时不要只看“CUDA 能不能用”:

nvidia-smi
python3 –version
python3 -c 'import torch; print(torch.__version__, torch.version.cuda, torch.cuda.device_count())'

需要确认的兼容关系包括:NVIDIA 驱动是否支持目标 CUDA、PyTorch 与推理引擎的 CUDA 构建是否匹配、GPU 显存是否能容纳模型权重和 KV Cache、跨卡连接是否具备 NVLink 或高速 PCIe,以及容器的 /dev/shm 是否足够。TensorRT-LLM 还要额外校验 TensorRT、CUDA、驱动和 Engine 构建环境的一致性。

模型下载目录最好使用本地 NVMe 或高性能共享存储,并提前完成权限、校验和缓存。第一次启动会加载权重、初始化 CUDA Kernel 和建立通信组,不能把“首次启动时间”当作正常请求延迟。

2. SGLang Docker 单机部署

开发和压测可以使用官方镜像。生产环境把 <version> 替换为经过验证的固定标签,并将模型通过只读卷挂载到容器:

docker run –rm –gpus all \\
–ipc=host \\
–shm-size=32g \\
–network host \\
-v /data/models/Qwen2.5-32B-Instruct:/models/Qwen2.5-32B-Instruct:ro \\
lmsysorg/sglang:<version> \\
python3 -m sglang.launch_server \\
–model-path /models/Qwen2.5-32B-Instruct \\
–served-model-name qwen2.5-32b \\
–host 0.0.0.0 \\
–port 30000 \\
–tp-size 4 \\
–context-length 32768 \\
–mem-fraction-static 0.85 \\
–enable-metrics

几个参数的含义:

参数作用使用建议
–model-path 本地目录或 Hugging Face 模型路径 生产使用固定 revision 的本地副本
–served-model-name API 中暴露的模型名 与网关路由和计费口径保持一致
–tp-size Tensor Parallel 并行度 通常与参与推理的 GPU 数量一致
–context-length 单请求最大上下文长度 按业务需要设置,越大越占 KV Cache
–mem-fraction-static 静态显存预算比例 留出通信、运行时和碎片空间后再提高
–enable-metrics 暴露 Prometheus 指标 生产环境应默认开启并纳入告警

–tp-size 4 并不意味着四张卡一定比一张卡快。Tensor Parallel 会引入跨卡通信,GPU 拓扑、模型大小和请求长度都会影响收益。小模型在 PCIe 机器上强行扩大 TP,可能反而降低吞吐。

3. vLLM Docker 部署

vLLM 可以通过 OpenAI-compatible server 直接提供统一的 /v1 接口。下面的命令适合单机压测或作为 Kubernetes 容器的启动参数;vllm/vllm-openai 的镜像标签和参数会随版本变化,正式部署前应以对应版本的 vllm serve –help 为准。

docker run –rm –gpus all \\
–ipc=host \\
–shm-size=32g \\
–network host \\
-v /data/models/Qwen2.5-32B-Instruct:/models/Qwen2.5-32B-Instruct:ro \\
vllm/vllm-openai:<version> \\
–model /models/Qwen2.5-32B-Instruct \\
–served-model-name qwen2.5-32b \\
–host 0.0.0.0 \\
–port 30000 \\
–tensor-parallel-size 4 \\
–max-model-len 32768 \\
–gpu-memory-utilization 0.85

vLLM 的 –tensor-parallel-size 与 SGLang 的 –tp-size 语义相近,但不能混用参数名。Prefix Caching、量化格式、最大并发和调度参数也应按 vLLM 当前版本的帮助信息逐项确认。生产环境建议为镜像、模型 revision 和启动参数建立可回滚的配置清单。

4. TensorRT-LLM Engine 构建与服务

TensorRT-LLM 通常不是启动容器后直接读取 Hugging Face 权重,而是先把模型转换为 checkpoint,再针对目标 GPU、精度和并行策略构建 TensorRT Engine。典型流程如下:

Hugging Face 模型
→ TensorRT-LLM checkpoint 转换
→ trtllm-build 构建 Engine
→ trtllm-serve 或 Triton Inference Server
→ OpenAI 兼容 API / 内部服务

以下命令是版本相关示例,具体的转换脚本路径、参数名和服务入口以所用 TensorRT-LLM 版本文档及 –help 输出为准:

# 1. 将 Hugging Face 权重转换为 TensorRT-LLM checkpoint
python examples/convert_checkpoint.py \\
–model_dir /models/Qwen2.5-32B-Instruct \\
–output_dir /tmp/qwen2.5-32b-ckpt \\
–dtype float16 \\
–tp_size 4

# 2. 针对目标 GPU 构建 Engine;FP16 也可以替换为 BF16、FP8 或 INT8
trtllm-build \\
–checkpoint_dir /tmp/qwen2.5-32b-ckpt \\
–output_dir /engines/qwen2.5-32b-tp4 \\
–gemm_plugin float16

# 3. 启动服务(不同版本可能使用 Triton 或其他 serving 入口)
trtllm-serve /engines/qwen2.5-32b-tp4 \\
–host 0.0.0.0 \\
–port 30000 \\
–served-model-name qwen2.5-32b

Engine 与 GPU 架构、TensorRT-LLM 版本、CUDA 版本和并行配置存在绑定关系。升级其中任一项都应重新构建并回归测试,不能把旧 Engine 直接复制到新运行时。TensorRT-LLM 适合模型、GPU 和精度相对固定且追求极致吞吐的场景;模型频繁变更或需要快速适配新架构时,SGLang、vLLM 通常更易迭代。

5. Kubernetes 部署骨架(以 SGLang 为例)

Kubernetes 中建议一个 Pod 绑定一组固定 GPU,并通过节点标签、RuntimeClass 和 GPU 资源限制保证调度稳定。下面是可作为起点的 Deployment,模型目录假设由 PVC 提供:

apiVersion: apps/v1
kind: Deployment
metadata:
name: sglangqwen
labels:
app: sglangqwen
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: sglangqwen
template:
metadata:
labels:
app: sglangqwen
spec:
nodeSelector:
accelerator: nvidiaa100
terminationGracePeriodSeconds: 120
containers:
name: server
image: lmsysorg/sglang:<version>
command: ["python3", "-m", "sglang.launch_server"]
args:
modelpath=/models/Qwen2.532BInstruct
servedmodelname=qwen2.532b
host=0.0.0.0
port=30000
tpsize=4
contextlength=32768
memfractionstatic=0.85
enablemetrics
ports:
name: http
containerPort: 30000
resources:
limits:
nvidia.com/gpu: "4"
memory: 64Gi
readinessProbe:
httpGet:
path: /health
port: http
periodSeconds: 10
failureThreshold: 30
livenessProbe:
httpGet:
path: /health
port: http
periodSeconds: 20
failureThreshold: 6
volumeMounts:
name: model
mountPath: /models
readOnly: true
volumes:
name: model
persistentVolumeClaim:
claimName: llmmodels

apiVersion: v1
kind: Service
metadata:
name: sglangqwen
spec:
selector:
app: sglangqwen
ports:
name: http
port: 30000
targetPort: http

模型加载通常需要几十秒到数分钟,readiness 必须在服务真正可以接收请求后才通过。生产发布建议使用新旧 Deployment 并行预热,再由网关切流;直接滚动重启唯一副本会造成较长不可用窗口。模型文件如果通过 Init Container 下载,要设置下载超时、校验和以及断点续传,避免每次重启都从公网重新拉取。

6. 从网关访问推理服务

三种推理服务都适合放在内网,外部鉴权、租户限流、配额和审计交给 AI Gateway。最少应在网关层补齐以下字段:request_id、trace_id、tenant、model、stream 和 max_tokens。这样才能把一次调用和指标、日志、Trace 关联起来。

7. OpenAI 兼容 API 调用

启动服务后,可以使用 curl 验证非流式接口:

curl http://127.0.0.1:30000/v1/chat/completions \\
-H 'Content-Type: application/json' \\
-d '{
"model": "qwen2.5-32b",
"messages": [
{"role": "system", "content": "你是一个严谨的运维助手。"},
{"role": "user", "content": "解释一次 API 延迟升高的排查顺序。"}
],
"temperature": 0.2,
"top_p": 0.9,
"max_tokens": 512,
"stream": false
}'

流式响应通过 SSE 返回,适合聊天界面和长文本生成:

curl -N http://127.0.0.1:30000/v1/chat/completions \\
-H 'Content-Type: application/json' \\
-d '{
"model": "qwen2.5-32b",
"messages": [{"role": "user", "content": "用三点说明 SGLang 的前缀缓存。"}],
"max_tokens": 256,
"stream": true
}'

业务服务也可以复用 OpenAI SDK,只需把 base_url 指向对应推理服务:

from openai import OpenAI

client = OpenAI(
base_url="http://inference-qwen:30000/v1",
api_key="internal-token",
)

response = client.chat.completions.create(
model="qwen2.5-32b",
messages=[{"role": "user", "content": "写一个 PostgreSQL 索引检查清单。"}],
temperature=0.1,
max_tokens=512,
)
print(response.choices[0].message.content)

三种引擎都提供不同程度的 OpenAI 兼容能力,但不等于所有 OpenAI 参数在所有模型和版本上都完全一致。接入前应建立参数兼容性测试,重点验证 stop、工具调用、JSON 输出、视觉输入、流式中断和错误码。

8. 采样参数如何影响结果

参数含义工程建议
temperature 调整采样随机性 分类、抽取等任务使用低值;创作任务再提高
top_p nucleus sampling 截断范围 通常只调一个随机性参数,避免组合失控
max_tokens 最大输出 Token 数 由业务上限控制,防止长输出占满并发
stop 提前结束生成的字符串 与模板和流式协议一起测试
stream 是否分片返回 长响应使用流式,但网关要正确处理断连

对结构化输出,优先使用模型和框架支持的 JSON Schema、正则或 choices 约束,并在服务端做最终 JSON 校验。不要只在 Prompt 中写“必须输出 JSON”,然后把未经校验的文本直接写入数据库。

9. 使用引擎原生前端

当流程包含多个生成步骤、候选选择或共享前缀时,引擎原生前端可以把编排逻辑放到服务端。下面以 SGLang 为例,vLLM 和 TensorRT-LLM 可使用各自的 Python API 或 Runtime:

import sglang as sgl

@sgl.function
def classify_and_explain(s, question):
s += "问题:" + question + "\\n"
s += "类别:" + sgl.gen("category", choices=["故障", "配置", "性能", "其他"]) + "\\n"
s += "解释:" + sgl.gen("explanation", max_tokens=256)

这类编排适合固定流程和可复用前缀。动态 Agent 仍应设置步骤数、总 Token、工具调用次数和超时,避免模型在服务端无限循环。

三、性能调优:从显存到吞吐(指标、量化与 PD 分离)

1. 先建立正确的性能指标

只看平均响应时间会掩盖排队和长尾问题。在线推理至少记录:

指标定义主要受什么影响
TTFT 请求到首个输出 Token 的时间 排队、Prefill、输入长度、前缀缓存
TPOT 相邻输出 Token 的平均间隔 Decode、GPU 利用率、并发和采样
E2E Latency 请求开始到完成的总时间 TTFT、输出长度、网络和客户端读取
Throughput 每秒生成 Token 或完成请求数 批处理、模型大小、并发和 GPU
Queue Time 进入队列到开始执行的时间 并发上限、调度策略和突发流量
Cache Hit Rate 前缀缓存命中比例 Prompt 稳定性和缓存容量

压测时固定模型 revision、输入输出长度和并发曲线,分别测冷启动、缓存命中、单请求、稳定并发和突发流量。把 P50、P95、P99 与 GPU 显存、功耗、温度、PCIe/NVLink 通信一起记录,才能判断是模型计算慢还是排队慢。

2. 显存预算与上下文长度

显存大致由四部分构成:模型权重、运行时临时张量、KV Cache 和通信/框架开销。量化只主要降低权重占用,不会按相同比例消除 KV Cache;当上下文很长、并发很高时,KV Cache 仍然可能成为瓶颈。

常用调优顺序如下:

  • 先确认模型权重和 Tokenizer 能在目标 GPU 上稳定加载。
  • 将上下文上限设为业务真实上限:SGLang 使用 –context-length,vLLM 使用 –max-model-len,TensorRT-LLM 通常在 Engine/profile 配置中固定,避免为极少数请求预留过大的 KV Cache。
  • 为运行时和通信预留显存余量:SGLang 可调整 –mem-fraction-static,vLLM 可调整 –gpu-memory-utilization,TensorRT-LLM 则需要在 Engine 构建和运行时配置 workspace、KV Cache 预算;确认稳定后再逐步提高利用率。
  • 设置引擎对应的在线并发上限:SGLang 常用 –max-running-requests,vLLM 可使用 –max-num-seqs 等调度参数,TensorRT-LLM 通过 batching/scheduler 配置控制;使用网关排队而不是让进程无界堆积。
  • 根据模型支持情况选择 FP8、AWQ、GPTQ 等量化方案,并重新评估准确率、首 Token 延迟和吞吐。
  • 发生 OOM 时,不要只重启 Pod。先确认是启动阶段权重 OOM、运行阶段 KV Cache OOM,还是长尾请求触发的碎片问题,再分别调整 TP、上下文、并发和量化配置。

    3. Tensor Parallel、Data Parallel 与副本

    Tensor Parallel(TP)把同一个模型拆到多张 GPU 上,适合单卡放不下或需要更高单实例吞吐的模型;代价是每一步都可能发生跨卡通信。Data Parallel(DP)是多个推理副本共同承接请求,适合模型能够放入每组 GPU、并且希望提升整体并发的场景。

    可以按下面的方式做容量设计:

    单 Pod 使用 GPU 数 = TP × DP
    集群总容量 = 单 Pod 每秒生成 Token × Pod 数量
    稳定并发上限 ≈ 可接受排队时间内的处理能力

    在有 NVLink 的机器上,优先让 TP 跨同一互联域;跨 NUMA、跨主机的 TP 需要高速网络和 NCCL 配置,不能照搬单机参数。若模型能在单卡或小 TP 上运行,通常增加多个副本比继续扩大 TP 更容易获得线性吞吐。

    4. 调度和前缀缓存调优

    连续批处理会在每轮 Decode 中动态加入新请求、移除已完成请求,提高 GPU 空闲时间的利用率。但并发不是越大越好:过大的批次会增加 TTFT 和长尾,过小的批次又无法发挥 GPU 吞吐。

    建议建立两类服务池:交互池优先保证 TTFT 和 P99,离线池优先追求每秒 Token;不要让批量评测或长文本总结占满交互池。对共享系统提示词和工具定义,固定模板和字段顺序,观察缓存命中率;命中率低时先检查 Prompt 拼接逻辑,再调整缓存预算。

    5. PD 分离:把 Prefill 与 Decode 拆成独立服务池

    PD 分离(Prefill/Decode Disaggregation,预填充与解码分离)确实属于性能调优实践,但它更接近“部署架构级调优”,而不是单个启动参数。Prefill 需要一次性处理大量输入 Token,通常更偏计算密集;Decode 每轮只生成少量 Token,更容易受显存带宽、KV Cache 访问和调度抖动影响。两者混在同一个实例时,长上下文 Prefill 可能挤占 Decode 的执行机会,导致 TTFT、TPOT 互相影响。

    典型的 PD 架构如下:

    客户端


    AI Gateway / PD Router
    ├─ Prefill Pool:处理输入 Token,生成 KV Cache
    │ │ KV Transfer(RDMA / NVLink / 高速网络)
    │ ▼
    └─ Decode Pool:加载或接收 KV Cache,持续生成 Token 并返回 SSE

    PD 分离的价值在于可以分别扩缩容和设置资源配额。例如,输入上下文很长但输出较短的知识库问答,可以增加 Prefill 副本;聊天和代码补全输出较长,则可以增加 Decode 副本。路由器还可以按租户、模型、上下文长度和服务等级把请求送入不同资源池。

    SGLang、vLLM 和 TensorRT-LLM 对 PD 分离、KV Transfer Connector、远程 KV Cache 和 Triton 编排的支持方式并不相同,部分能力仍处于实验或快速演进阶段。不要只看到文档中的功能名就直接上线,应确认目标版本是否支持当前模型、并行方式和网络拓扑,并完成端到端压测。

    判断条件更适合采用 PD 分离暂不建议采用
    负载特征 长上下文、Prefill 和 Decode 资源需求差异明显 单请求、短上下文、并发很低
    目标 同时压低 TTFT 和 TPOT,或需要独立扩缩容 只追求单请求最低延迟
    网络 具备低延迟、高带宽的 NVLink、RoCE 或 InfiniBand 仅有普通跨机网络,KV 传输占比高
    运维 有成熟的路由、预热、故障转移和容量治理 团队尚未建立多池发布和排障能力

    落地时至少观测四类数据:Prefill 排队时间、Decode 排队时间、KV 传输字节数与耗时、端到端 TTFT/TPOT。只有当“减少互相干扰”带来的收益大于 KV 传输和额外副本成本时,PD 分离才是正收益。KV 传输失败时应有重试或回退到合并实例的策略,否则一个网络抖动就可能放大为整条请求链路失败。

    6. 与 PD 分离配套的进阶优化

    PD 分离之外,还有几类经常组合使用的优化。它们解决的问题不同,不能简单叠加后期待线性收益:

    优化实践主要解决的问题适用场景主要代价或风险
    Chunked Prefill 长输入一次 Prefill 阻塞 Decode 长上下文和交互请求混部 切块过小会增加调度开销,TTFT 可能变长
    Speculative Decoding Decode 每步生成速度不足 输出较长、草稿模型与目标模型相近 需要额外草稿模型,接受率低时收益有限
    KV Cache 分层/卸载 GPU 显存不足、并发受限 长会话、低频缓存和超长上下文 CPU/NVMe 传输延迟高,需控制冷热数据
    Prefix Cache 重复系统提示词导致 Prefill 重算 多轮对话、RAG、工具调用 Prompt 规范稍有变化就会失效并占用显存
    MoE Expert Parallel MoE 模型专家计算和显存分布不均 Mixtral、Qwen-MoE 等稀疏模型 All-to-All 通信和专家负载倾斜
    请求分级与路由 长短请求互相影响、突发流量排队 交互、批处理、离线任务并存 需要网关识别 Token 预算并维护多个服务池

    Chunked Prefill。

    Chunked Prefill 把长输入拆成多个小块,在块与块之间让 Decode 请求获得调度机会。它可以在不完全拆分服务的情况下缓解“长 Prefill 阻塞短请求”,适合先做单实例优化。块大小应通过 TTFT、TPOT 和 GPU 利用率压测确定;并不是越小越好。

    Speculative Decoding。

    Speculative Decoding 先由较小的草稿模型提出多个候选 Token,再由目标模型批量校验,校验通过的 Token 可以一次提交,从而减少目标模型逐 Token Decode 的轮数。它通常对输出较长、草稿模型与目标模型分布接近的任务更有效;摘要、代码和严格格式输出应分别测量接受率和质量,不能只看理论加速比。

    KV Cache 分层与卸载。

    可以把 KV Cache 按冷热程度放在 GPU HBM、CPU 内存甚至本地 NVMe 中,或者使用独立的远程 KV Cache 服务。热数据留在 GPU,冷数据在请求再次命中时回迁。该方案能提高可容纳的会话数,但会引入传输延迟和一致性问题;应设置 TTL、容量上限和租户隔离,并把命中率、回迁耗时和淘汰次数纳入监控。

    MoE 的 Expert Parallel。

    对 Mixture-of-Experts(MoE)模型,Expert Parallel(EP)可以把不同专家分布到不同 GPU,再通过路由只激活部分专家。它与 TP、DP 可以组合,但会增加 All-to-All 通信。优化重点是专家负载均衡、通信拓扑和 batch 组成;当少数专家长期过热时,单纯增加 GPU 数量不一定有效,需要调整路由、容量因子或副本策略。

    这些优化建议按“先测量、后改动”的顺序推进:先用统一请求集建立基线,再一次只改变一个变量,记录 TTFT、TPOT、P99、吞吐、GPU 显存、KV Cache 命中率和单位 Token 成本。任何优化都必须有回滚开关,避免性能提升却带来准确率、稳定性或运维复杂度的不可控变化。

    7. 量化、FlashInfer 与 Kernel 选择

    量化可以降低显存和带宽压力,但不同模型、层和任务对精度敏感度不同。上线前至少比较四项:任务准确率、TTFT、TPOT 和峰值显存。不要仅凭模型文件大小选择量化格式。

    SGLang、vLLM 和 TensorRT-LLM 都会根据版本和硬件选择 Attention、采样和通信实现。SGLang、vLLM 常见 FlashInfer、PagedAttention 或 CUDA Graph 后端,TensorRT-LLM 则更多依赖构建 Engine 时确定的融合 Kernel 和 CUDA Graph 配置。遇到升级后性能回退时,应保存启动日志、实际生效的 backend 和 Engine 元数据,使用同一组请求做 A/B 测试,避免同时更换模型、驱动和框架版本。

    四、生产实践:生产治理、监控与排障

    1. 监控和日志

    开启引擎对应的 metrics 选项后,将 SGLang、vLLM 或 Triton/TensorRT-LLM 的指标端点纳入 Prometheus 或 vmagent。Grafana 看板至少应包括:请求数、成功率、5xx、TTFT、TPOT、E2E P99、队列长度、运行中请求数、输入/输出 Token、KV Cache 使用率、缓存命中率和模型加载状态。采用 PD 分离时,还要按 Prefill Pool、Decode Pool 分别展示队列长度、GPU 利用率、处理 Token 数,并记录 KV Transfer 的字节数、耗时、失败率和回退次数。TensorRT-LLM 经 Triton 部署时,还应采集 Triton 的请求队列、批处理和实例级指标。

    不同版本的指标名称可能变化,接入时应先抓取 /metrics 确认实际名称,再编写录制规则和告警。不要在看板中硬编码某个版本的指标名而不做升级验证。

    日志建议包含以下字段,并传递到 ELK:

    {
    "timestamp": "2026-09-12T08:30:00Z",
    "service": "inference-qwen",
    "engine": "sglang",
    "model": "qwen2.5-32b",
    "request_id": "req-abc123",
    "trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
    "input_tokens": 2048,
    "output_tokens": 256,
    "ttft_ms": 420,
    "status": "ok"
    }

    模型 Prompt、用户输入和输出内容可能包含隐私或密钥。默认只记录长度、哈希、错误类型和采样后的片段;需要审计全文时单独走权限、脱敏和保留周期,不要把原始内容无条件写入普通日志。

    2. 告警和弹性策略

    指标告警可以由夜莺或其他告警平台统一管理,典型规则包括:

    推理服务进程不可用持续 2 分钟 → Critical
    5 分钟 P99 TTFT 超过目标值 → Warning / Critical
    KV Cache 使用率持续超过 90% → Warning
    GPU 温度、XID、ECC 错误异常 → Critical
    5xx 或 OOM 次数在窗口内快速增长 → Critical
    请求队列持续增长且无下降趋势 → Warning
    KV Transfer 失败率或回退次数持续升高 → Critical

    弹性伸缩不要只依据 CPU。推理服务的主要瓶颈往往是 GPU 显存、KV Cache 和队列长度;而新 Pod 的模型加载时间又可能很长。更可靠的方式是:网关按租户和模型限流,使用队列长度或等待时间触发扩容,提前预热备用副本,缩容时先停止接收新请求并等待流式请求完成。

    3. 发布、升级与安全边界

    生产发布建议采用以下流程:

  • 固定镜像、推理引擎、PyTorch/TensorRT、CUDA、驱动和模型 revision,记录 SBOM 与校验值。
  • 使用离线或受控网络下载模型,校验文件完整性,禁止运行时任意拉取远程代码。
  • 新版本先启动影子实例,回放脱敏请求,比较准确率、TTFT、TPOT、显存和错误率。
  • 通过网关按租户或比例灰度,保留旧版本直到错误预算和长尾指标稳定。
  • 回滚时切回旧服务,不要在原 Pod 上直接替换模型目录。
  • 推理服务不应直接暴露公网。API Key、OAuth、租户配额、请求体大小、模型白名单和审计应放在网关;服务到服务通信使用 mTLS 或内网策略。–trust-remote-code 会允许执行模型仓库中的自定义代码,只有在审核来源和版本后才开启,并将模型目录设置为只读。TensorRT-LLM 的 Engine 文件也应视为受保护的构建产物,只允许来自已审核流水线。

    4. 常见故障排查

    问题一:服务启动时报 CUDA out of memory。

    先区分模型权重无法加载,还是运行时初始化失败。检查模型精度、GPU 显存、TP 数量和是否有其他进程占卡;再降低上下文长度、引擎显存预算或选择量化模型。不要只增加 TP,跨卡通信和模型切分约束可能让问题更复杂。

    问题二:GPU 利用率不高,但请求很慢。

    优先查看 Queue Time、TTFT 和输入长度。如果队列时间高,说明并发限制或调度策略在等待;如果 Prefill 时间高,检查长上下文和前缀缓存;如果 Decode 间隔高,检查输出长度、批次、采样和 GPU 时钟。CPU Tokenizer、网络发送阻塞和客户端没有及时读取 SSE,也可能让 GPU 看起来不忙。

    问题三:多卡启动后卡住或 NCCL 报错。

    检查容器是否使用 –ipc=host、共享内存是否足够、各卡驱动和 CUDA 是否一致、NCCL 网卡选择是否正确,以及 Pod 是否被调度到同一台机器。跨主机 TP 还要验证 RDMA、端口、安全组和 NCCL_SOCKET_IFNAME 等配置。

    问题四:首 Token 延迟突然升高。

    检查是否发生前缀缓存未命中、模型刚重启、长请求突发或 GPU 降频。将系统 Prompt、工具定义和消息模板固定下来,区分冷缓存与热缓存压测;不要只看平均值,要观察 P95/P99 和排队时间。

    问题五:流式输出中途断开。

    检查网关和负载均衡器的响应超时、SSE 缓冲、客户端取消传播和服务端优雅退出。网关要透传 text/event-stream,定期发送心跳或保持数据刷新,并在取消时及时释放生成请求和 KV Cache。

    问题六:结构化输出偶尔不是合法 JSON。

    确认使用的模型、推理引擎版本和 API 参数确实支持目标约束;为 JSON Schema、正则和 stop 条件建立回归测试,服务端对结果做解析校验,失败时进行有限次数重试或返回明确错误,不能把校验责任全部交给前端。

    问题七:启用 PD 分离后,TTFT 反而升高或请求偶发失败。

    先分别查看 Prefill、KV Transfer 和 Decode 三段耗时,确认是否是网络传输、KV Cache 格式不兼容、两侧 TP/PP 配置不一致或路由器重复转发。普通跨机网络下,KV Transfer 可能抵消 Prefill 并行收益;应降低传输距离、使用 RDMA/NVLink,或暂时回退到合并实例。生产上必须保留回退路径,并为转移超时、版本不匹配和目标 Decode 实例不可用设置明确错误码。

    5. 常见问答

    Q:SGLang、vLLM 和 TensorRT-LLM,哪个一定更快?

    A:没有脱离负载的固定答案。SGLang 在共享前缀、多轮对话和结构化生成场景可能优势明显,vLLM 通用服务和模型适配经验丰富,TensorRT-LLM 在固定 NVIDIA GPU 和 Engine 的场景可能取得更高吞吐。最终应使用生产请求分布做压测,至少比较 TTFT、TPOT、P99、吞吐、显存和运维成本。

    Q:TP 越大越好吗?

    A:不是。SGLang 使用 –tp-size,vLLM 使用 –tensor-parallel-size,TensorRT-LLM 通常在 Engine 构建阶段配置 TP/PP。TP 解决单卡放不下或单实例吞吐不足的问题,但会增加跨卡通信。模型能在单卡或小 TP 上稳定运行时,增加多个副本往往比扩大 TP 更容易提升整体吞吐。

    Q:为什么已经开启前缀缓存,命中率还是很低?

    A:缓存按 Token 前缀匹配。系统提示词的空格、工具列表顺序、Chat Template、版本字段或动态内容放置位置变化,都会破坏复用。应固定序列化模板,把稳定内容放在前面,并直接查看运行指标确认命中率。

    Q:推理服务需要自己实现鉴权吗?

    A:服务可以放置最基础的访问控制,但生产上应由 AI Gateway 统一负责 API Key、OAuth、租户限流、配额、审计和模型白名单。三种引擎只暴露在受控网络中,便于升级和隔离。

    6. 一份上线检查清单

    [ ] 固定推理引擎、PyTorch/TensorRT、CUDA、驱动和模型 revision
    [ ] 完成单请求、缓存命中、稳定并发和突发流量压测
    [ ] 明确 TP/DP、GPU 拓扑、/dev/shm 和 NCCL 配置
    [ ] 设置上下文、输出 Token、并发和请求体大小上限
    [ ] readiness 等待模型真正加载完成,发布支持回滚
    [ ] /metrics 已接入 Prometheus/vmagent,Grafana 看板可用
    [ ] TTFT、TPOT、P99、队列、KV Cache、GPU 和 OOM 已告警
    [ ] 若采用 PD 分离,已验证 KV Transfer、网络带宽、回退路径和两侧版本兼容性
    [ ] 日志包含 request_id、trace_id、model 和 Token 统计并完成脱敏
    [ ] 网关已配置鉴权、限流、SSE 超时和客户端取消传播
    [ ] 已演练 OOM、NCCL 故障、模型加载失败和通知失败

    五、平台化演进:多模型、多租户、容量与成本治理

    单个模型能够稳定提供服务,只是推理平台的起点。当模型数量、业务团队和调用量增加后,新的瓶颈通常出现在模型发布、资源分配、租户隔离和成本核算,而不再只是某一张 GPU 的利用率。平台化的目标是让模型从“手工启动的进程”变成可注册、可路由、可计量、可回滚的标准服务。

    1. 多模型注册与智能路由

    建议建立统一的模型注册表,至少记录模型名称、版本或 revision、量化格式、上下文上限、所需 GPU、适配的引擎、SLO 和数据合规等级。模型权重、启动参数和 Engine 应作为不可变制品管理,避免同一个模型名在不同节点实际运行不同版本。

    网关或模型路由层可以根据以下维度选择后端:

    路由维度示例策略目的
    任务类型 对话走通用模型,代码走代码模型,Embedding 走专用服务 减少错误选型和无效消耗
    上下文长度 短请求走低延迟池,超长请求走长上下文池 避免长请求拖慢交互流量
    服务等级 高优先级租户走预热副本,普通任务允许排队 保证不同 SLA
    引擎能力 需要结构化生成时路由到支持约束的引擎 避免 API 能力不匹配
    发布状态 按租户或比例切到 canary,异常时回退 stable 支持灰度与快速回滚

    路由策略应避免“只看 GPU 空闲率”。更有价值的信号包括预计输入 Token、预计输出 Token、队列等待时间、KV Cache 命中率和模型加载状态。对同一模型的多个副本,可以使用最短队列、加权轮询或基于 Token 预算的调度;对不同模型,则要把质量、延迟和成本一起纳入选择。

    2. 多租户隔离、配额与公平调度

    多租户环境至少需要四层隔离:网络访问隔离、模型白名单隔离、并发与 Token 配额隔离、日志和数据权限隔离。不要只限制 QPS,因为一个请求可能包含很长的输入和输出;更合理的配额单位是输入 Token、输出 Token、并发请求数和 GPU 时间的组合。

    可以按租户维护以下策略:

    租户配额 = 每分钟请求数 + 每分钟输入 Token + 每分钟输出 Token
    单请求上限 = 最大上下文 Token + 最大输出 Token + 请求体大小
    并发上限 = 交互请求并发 + 流式请求并发 + 离线任务并发

    调度器应支持超额拒绝、排队、降级模型和优先级继承。高优先级不能无限挤占系统资源,否则低优先级任务会形成饥饿;建议为每个租户设置最大排队时间,并在网关返回可重试的错误码。指标标签中不要直接使用任意用户 ID,否则 Prometheus 会产生高基数;租户明细可以放在日志或计费系统中。

    3. 容量规划与单位 Token 成本

    容量规划不能只用“GPU 利用率达到 80%”作为扩容依据。应先根据生产请求分布测出有效吞吐,再结合 SLO 反推副本数量。一个简单的估算公式是:

    所需副本数 ≈ 峰值 Token 速率 ÷ 单副本在目标 P99 下的有效 Token 速率
    单位 Token 成本 ≈ (GPU 小时成本 × GPU 数 × 运行小时 + 存储与网络成本)÷ 实际处理 Token 数

    “有效 Token 速率”必须包含排队、失败重试、预热和低负载时段,不能直接使用压测报告中的峰值。对于 PD 分离架构,还要分别计算 Prefill 和 Decode 池的容量,避免一侧扩容后另一侧成为瓶颈。扩容触发可以组合队列等待时间、预计 Token 负载、GPU 显存水位和错误率;缩容前要等待流式请求完成,并保留足够的热副本。

    成本优化通常有以下顺序:先清理无效重试和过大的 max_tokens,再优化 Prefix Cache 命中率和批处理,之后才考虑更激进的量化、低价 GPU 或跨地域调度。任何降本方案都必须同时回归准确率、P99 和故障恢复时间,不能只看云账单下降。

    4. 异构 GPU、Engine 兼容与多地域容灾

    不同 GPU 架构对 FP8、BF16、FlashInfer、TensorRT Engine 和显存容量的支持不同。平台应维护“模型—引擎—GPU—精度”的兼容矩阵,调度时把节点标签、驱动版本、CUDA 版本和 Engine 元数据作为硬约束。TensorRT-LLM Engine 尤其不能跨不兼容的 GPU 架构直接复用;SGLang 和 vLLM 也需要验证对应版本的 Kernel 和量化后端。

    多地域部署时,可以按数据合规、网络距离和容量水位选择主区域与备用区域。跨地域只同步模型制品和配置,不应默认转发包含用户原文的请求;故障切换前要明确会话状态、Prefix Cache 和流式请求如何处理。推荐采用“区域内多副本 + 区域间冷备或热备”的分层策略,并定期演练 DNS、网关、模型仓库和密钥系统同时异常的情况。

    5. 从单服务到推理平台的演进路线

    可以按以下阶段推进,避免一开始就引入过多复杂组件:

    阶段重点能力验收标准
    P0 单模型服务 固定版本、健康检查、OpenAI API、基础指标 能稳定发布和回滚
    P1 标准化服务 模型注册表、统一网关、配额、日志和成本标签 多个模型使用同一套流程
    P2 性能池化 交互/离线分池、Prefix Cache、Chunked Prefill、PD 分离 TTFT、TPOT 和吞吐达到目标
    P3 平台治理 多地域、灾备、计费、质量评估和自动化扩缩容 故障可切换,成本可解释

    每个阶段都应保留清晰的回退路径。只有当请求分布、网络条件和团队运维能力都达到要求时,才把单体服务升级为 PD 分离、远程 KV Cache 或跨地域调度;复杂度本身不是性能指标。

    结语

    推理引擎的工程价值在于把模型推理中的重复计算、请求调度和生成控制交给专门的 runtime 管理。真正上线时,重点不应只是启动命令,而是建立一套完整边界:SGLang、vLLM 或 TensorRT-LLM 负责高效执行,GPU 和 Kubernetes 负责资源隔离,AI Gateway 负责身份与流量治理,Prometheus/vmagent、Grafana、ELK 和夜莺负责可观测与告警;平台层再负责模型注册、路由、配额、容量和成本治理。

    当团队能够同时回答“当前排队多长、首 Token 为什么慢、前缀缓存是否命中、显存还剩多少、哪个租户受到影响、如何快速回滚”时,模型才算从实验环境进入了可运营的推理平台。

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 【推理引擎】大模型推理服务部署、性能调优与生产实践:SGLang、vLLM、TensorRT-LLM
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!