前言:为什么你需要了解 vLLM
如果你正在做大模型相关的开发或运维工作,vLLM 是一个绕不开的名字。简单来说,vLLM 是一个专为大语言模型推理优化的 高性能引擎,它的核心价值可以用一句话概括:让 GPU 干更多的活,花更少的钱。
vLLM 的核心优势:
- 极高的显存效率:消除 KV Cache 内存碎片,几乎零浪费
- 超高并发吞吐:支持连续批处理,单卡可同时处理上百个请求
- OpenAI 兼容接口:零成本迁移现有业务代码
- 丰富的模型支持:覆盖 Llama、Qwen、DeepSeek、Mistral 等几乎所有主流模型
- 企业级特性:量化、多卡并行、前缀缓存、健康检查、Prometheus 监控等
如果你正在做 LLM 私有化部署,vLLM 几乎是绕不开的技术选型。
目前,包括 Meta、Google、Character.AI 等科技巨头都在生产环境中使用 vLLM。LinkedIn 更是用 vLLM 支撑了超过 50 个不同的 GenAI 应用场景,运行在数千台生产环境的主机上。Stripe 迁移到 vLLM 后,推理成本降低了 73%。
第一部分:vLLM 核心原理(理解它,才能用好它)
1.1 大模型推理的两大阶段
在理解 vLLM 之前,先搞清楚 LLM 推理是怎么工作的。推理分为两个阶段:
- 预填充阶段(Prefill) :模型处理输入提示词,每个输入词元生成对应的键和值,存入 KV 缓存。
- 解码阶段(Decode) :模型逐个生成新词元,复用已有的 KV 缓存来计算。
随着提示词和生成内容增加,KV 缓存会越来越大,成为内存消耗的"大户"。
举例说明:
大模型回答你问题分两步干活,中间会存一堆临时数据(KV缓存),这堆数据越堆越大,占超多显存,vLLM就是专门解决这个显存浪费问题的工具。
- 预填充阶段(Prefill)= 读完你的提问
你发给AI一整段问题(比如"写一篇作文"),AI一次性把你所有文字全部读一遍。
读的时候会生成一堆临时计算数据,全部存到显存里,这堆数据就是KV缓存 。
简单记:一次性读完你的问题,存好中间计算数据。
假设你输入提问:小猫喜欢吃鱼。
一共 4 个词元:小猫、喜欢、吃、鱼
- 处理词:小猫
模型算出一串数字向量:
K₁ = 0.2, 0.8, -0.1, 0.5...... (小猫的身份标识:代表它是动物、小型、毛茸茸这类特征)
V₁ = 0.7, 0.1, 0.3, -0.4...... (小猫本身携带的完整语义信息)- 处理词:喜欢
K₂ = 0.1, 0.9, 0.2, -0.3......("喜欢" 这个动词的身份)
V₂ = 0.5, 0.2, -0.6, 0.7......("喜欢" 代表的情绪、动作信息)- 处理词:吃
K₃、V₃ 同理,专属数字数组- 处理词:鱼
K₄、V₄ 同理,专属数字数组
- 解码阶段(Decode)= AI一个字一个字输出回答
AI不会一次性吐出整篇答案,是一个字、一个词慢慢蹦出来。
每生成一个新字,不用重新再读一遍你的问题,直接复用刚才存好的KV缓存,只算新字就行,省计算量。
简单记:逐字输出回答,反复用之前存好的数据。
加入 Ai 的回答是: 「因为鱼儿是猫的最爱」
- AI 第一个输出字:因
不用重新计算「小猫喜欢吃鱼」整段,直接调取现成 K1-K4、V1-V4,只单独算新字「因」,得到 K5、V5,追加进 KV 缓存。
现在缓存变成:K1K5、V1V5- 再输出第二个字:为
复用全部旧缓存 K1-K5、V1-V5,新增 K6、V6,缓存继续变大。- 直观变化过程
输入 4 个字 → KV 只有 4 组数据
输出第 1 个字 → 5 组
输出第 2 个字 → 6 组
输出 100 个字 → 104 组
1.2 传统方案的痛点
传统方案中,KV 缓存管理存在严重的 内存碎片 问题------60-80% 的 GPU 内存被白白浪费 。
这就好比你在一个仓库里随机堆放货物,很快空间就变得七零八落,明明还有空位却放不下新东西。
1.3 vLLM 的核心创新
vLLM 通过两项关键技术解决了这个问题:
PagedAttention(分页注意力) :借鉴操作系统内存分页的思想,将 KV 缓存按"页"来管理,消除了内存碎片。
这使得 GPU 内存利用率从传统方案的 20-40% 提升到 90% 以上。
连续批处理(Continuous Batching) :传统方案必须等一个请求全部处理完才能处理下一个。vLLM 可以在处理当前请求的同时,动态插入新请求,GPU 永远在干活,从不空转。
这两项技术结合,vLLM 相比传统方案可提供 2-24 倍的吞吐量提升。
第二部分:快速入门
2.1 环境准备
vLLM 要求 Linux 操作系统,Python 3.10-3.13。推荐使用 NVIDIA GPU,计算能力 ≥ 7.0。
2.2 安装 vLLM
先使用 mamba 创建 虚拟环境:
bash
pip install vllm
2.3 第一个推理示例
用 Python 代码跑一个简单的离线推理:
python
from vllm import LLM, SamplingParams
# 初始化Qwen2-7B-Instruct模型
llm = LLM(
model="/root/autodl-tmp/Qwen2-7B-Instruct",
trust_remote_code=True, # 加载通义千问系列必填
max_model_len=8192, # 和命令行保持一致上下文长度
gpu_memory_utilization=0.85 # 显存占用比例
)
# 采样参数
sampling_params = SamplingParams(temperature=0.7, top_p=0.9)
# 推理
outputs = llm.generate("解释量子计算的基本原理", sampling_params)
# 打印结果
print(outputs[0].outputs[0].text)
2.4 启动 OpenAI 兼容的 API 服务
这是 企业级 最常用的方式------启动一个 HTTP 服务,让其他应用调用:
bash
vllm serve
--model "/root/autodl-tmp/Qwen2-7B-Instruct" \
--host 0.0.0.0 \
--port 8001 \
--max-model-len 8192 \
--gpu-memory-utilization 0.85 \
--trust-remote-code
- --model 这个其实可以省略,vllm serve 后的 第一个位置 参数 本身就是 model 路径,不用写 --model 也是可以的,而且 通常都不写
- --host 0.0.0.0 企业部署必加,否则只能本机访问;
- 默认端口 8000,想更换端口追加 --port 自定义端口。
- --gpu-memory-utilization 0.85 控制显卡显存占用比例,预留少量显存给系统;
- --max-model-len 8192 上下文窗口长度,按需调大 / 调小;
- --trust-remote-code 加载 Qwen 系列模型必需,执行模型内自定义代码;
服务启动后,就可以用 OpenAI 的客户端调用了,因为 vLLM 完全兼容 OpenAI API 格式,可以直接使用 OpenAI SDK:
python
from openai import OpenAI
# 初始化客户端
client = OpenAI(
api_key="EMPTY", # vLLM 默认不需要密钥
base_url="http://localhost:8001/v1"
)
# 非流式调用
response = client.chat.completions.create(
model="Qwen/Qwen2.5-7B-Instruct",
messages=[
{"role": "system", "content": "你是一个专业的技术助手。"},
{"role": "user", "content": "用一句话解释什么是 PagedAttention"}
],
temperature=0.7,
max_tokens=200
)
print(response.choices[0].message.content)
流式调用(SSE):
python
stream = client.chat.completions.create(
model="Qwen/Qwen2.5-7B-Instruct",
messages=[{"role": "user", "content": "写一篇关于 vLLM 的介绍"}],
stream=True,
max_tokens=500
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
2.5 健康检查
vLLM 内置健康检查端点:
bash
# 检查服务是否正常
curl http://localhost:8001/health
# 查看运行统计
curl http://localhost:8001/stats
第三部分:核心参数详解(调优必知)
3.1 启动参数全景
| 参数 | 含义 | 建议值 |
|---|---|---|
--model |
模型名称或路径 | 必填 |
--tensor-parallel-size |
张量并行度(用几张卡) | 根据 GPU 数量和模型大小 |
--gpu-memory-utilization |
GPU 显存利用率 | 0.85-0.90(留余量) |
--max-num-seqs |
最大并发序列数 | A100 从 64-128 起步 |
--max-model-len |
最大序列长度 | 按实际需求设,别设太大 |
--dtype |
数据类型 | bfloat16 / float16 |
--quantization |
量化方式 | awq / aqlm / fp8 |
3.2 关键参数详解
--gpu-memory-utilization (GPU 显存利用率):
控制 vLLM 使用多少 GPU 显存。
- 默认值:0.9
- 作用:vLLM 启动时计算可用显存,按此比例分配给 KV Cache
- 调优建议 :
- 保守起步:0.85(预留 15% 给 CUDA Kernel、临时张量等)
- 逐步上调:每次 +0.02,直到出现 OOM 再回退 0.02
- 长上下文场景:适当降低到 0.75~0.8
--max-num-seqs :(最大并发请求数)
限制同时处理的请求数。 这个参数直接影响吞吐量。
- 默认值:256(v0 版本);v1 版本建议调低
- 作用:同一时刻最多处理的请求序列数量
- 调优建议 :
- 7B 模型单卡:32 ~ 128
- 13B 模型单卡:16 ~ 64
- 70B 模型多卡:4 ~ 16
- v1 版本注意:warmup 阶段会为每个序列预分配采样器显存,256 默认值极易 OOM,建议从 64 开始试,逐步调高直到首 token 延迟开始变差为止。
--tensor-parallel-size 张量并行度(用几张卡):
当模型单卡装不下时,用多卡并行。需要 NVLink 等高速互联。
物理限制: 单机多显卡。
--max-model-len (最大上下文长度):
限制单次请求里,「你的提问 + AI 回答」加起来最多能容纳多少个字元(token)。
和前面 KV 缓存挂钩,每 1 个 token 都会生成一组 K、V 存入 KV 缓存。
max-model-len 同时控制单个请求 KV 缓存的最大上限
- 作用:限制每个请求的最大 token 数(输入+输出)
- 新手大坑:不设置的话,vLLM 会用模型配置的理论最大值(如 128K),直接 OOM
- 最佳实践 :
- 根据业务实际需求设置,不要贪大
- v0.18.0+ 支持
--max-model-len auto,自动根据可用显存推算 - 业务场景固定时,显式指定比 auto 更可控
--block-size(KV Cache 块大小)
- 默认值:16
- 作用:每个物理块存放的 token 数量
- 调优建议 :
- 一般保持默认即可
- 超长上下文可设为 32,减少页表开销
- MoE 模型(如 DeepSeek-V3)建议设为 1
--swap-space(CPU 交换空间,单位 GB)
- 作用:显存不足时,把不活跃的 KV Cache 换出到 CPU 内存
- 默认值:4
- 适用场景:突发高并发、偶尔超长请求
- 注意:换入换出有延迟开销,不能当作常态解决方案
--max-num-batched-tokens(单步最大批处理 token 数)
- 作用:每个推理步长中,所有请求加起来最多处理的 token 总数
- 影响:值越大,单步计算量越大,吞吐越高,但首 token 延迟可能增加
- 推荐值 :
- 高吞吐场景:8192 ~ 16384
- 低延迟场景:2048 ~ 4096
--enable-prefix-caching(启用前缀缓存)
- 作用:自动缓存相同的前缀 KV Cache(如 system prompt、RAG 检索的文档)
- 适用场景 :
- RAG 系统(大量重复的检索上下文)
- Agent 系统(固定的工具描述前缀)
- 多轮对话中用户重复提问的场景
- 效果:命中时首 token 延迟大幅降低,显存占用减少
--chunked-prefill-size(分块预填充大小)
- 作用:把超长输入分成多个小块逐步处理,避免预填充阶段占用全部算力
- 好处:长输入不会阻塞其他短请求的生成,提升公平性
- 推荐值:2048 ~ 4096
3.3 不同场景 配置模板
场景一:低延迟在线对话(客服 / 聊天机器人)
bash
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-7B-Instruct \
--gpu-memory-utilization 0.80 \
--max-num-seqs 32 \
--max-model-len 4096 \
--max-num-batched-tokens 2048 \
--enable-prefix-caching
场景二:高吞吐批处理(数据标注 / 批量生成)
bash
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-7B-Instruct \
--gpu-memory-utilization 0.95 \
--max-num-seqs 128 \
--max-model-len 8192 \
--max-num-batched-tokens 16384
场景三:长文档处理(RAG / 文档总结)
bash
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-14B-Instruct \
--gpu-memory-utilization 0.85 \
--max-num-seqs 16 \
--max-model-len 32768 \
--chunked-prefill-size 4096 \
--kv-cache-dtype fp8 \
--enable-prefix-caching
第四部分:性能调优实战(让 vLLM 真正"干活")
很多团队把 vLLM 当 demo 跑,但其实没有发挥它的系统能力。以下是在生产环境中反复验证的调优手段。
4.1 请求塑形(Request Shaping)
vLLM 的核心优势在于连续批处理,把多个请求的 token 打包进同一个计算步骤。想让这个机制发挥最大效果,客户端需要配合:
- 控制
max_tokens:聊天场景 256-512 基本够用。那种动不动生成几千 token 的请求会拖垮整个 batch 的效率。 - 使用流式返回:降低用户感知延迟,同时让 batch 持续运转。
- 保持 prompt 长度相对统一:长短差异太大会影响 packing 效率。
python
# 客户端最佳实践:异步流式 + 并发控制
import asyncio
from openai import AsyncOpenAI
client = AsyncOpenAI(base_url="http://localhost:8000/v1", api_key="NOT_NEEDED")
SEM = asyncio.Semaphore(128) # 控制并发请求数
async def ask(msg: str):
async with SEM:
stream = await client.chat.completions.create(
model="your-model",
messages=[{"role": "user", "content": msg}],
max_tokens=256, # 一定要限制!
stream=True
)
out = []
async for chunk in stream:
token = chunk.choices[0].delta.content or ""
out.append(token)
return "".join(out)
4.2 KV 缓存复用(前缀缓存)
这是"白捡"的性能提升。当两个请求共享相同前缀时(如相同的系统提示词、few-shot 示例),vLLM 直接复用 KV 缓存,零成本加速。
关键原则:system prompt 必须固定不变,连标点和空格都不能改。动态内容全部放在用户消息末尾。
python
# 好的做法:system prompt 完全固定
SYSTEM = (
"You are a helpful assistant. "
"Use bullet points. "
"Cite numbers when you can.\n" # 完全固定,字节级一致
)
def build_messages(user_msg: str):
return [
{"role": "system", "content": SYSTEM},
{"role": "user", "content": user_msg}, # 只有这里是动态的
]
RAG 场景下,把模板和指令缓存起来,每个请求只追加检索到的事实,收益非常明显。
4.3 量化(Quantization)
用 AWQ 做 4-bit 权重量化,内存占用大幅降低,精度几乎不掉。KV 缓存也可以量化,缓存占用减少意味着能跑更多并发序列。
经验法则:GPU 内存紧张时就量化。更多并行序列带来的收益通常远超全精度权重那点质量提升。
bash
vllm serve /path/to/awq-model \
--quantization awq \
--dtype auto
4.4 推测解码(Speculative Decoding)
用一个 1B 到 8B 的小模型做"草稿模型",大模型负责验证。在 temperature 0.3-0.9 区间、中等长度输出的场景效果最好。
bash
vllm serve main-model \
--speculative-draft-model tiny-draft-model
需要持续监控 acceptance rate 和 draft 效率。
4.5 容量规划:看令牌率,而不是 QPS
两个请求 QPS 一样,token 的预算可能天差地别。规划容量要用 输入 + 输出的 token/秒 来衡量。
text
容量 ≈ GPU数量 × 单卡持续token/秒 × 利用率
利用率保持在 70-85% 能吸收峰值,超过 90% 可能会莫名其妙地变慢。
第五部分:企业级部署(从开发到生产)
5.1 容器化部署(Docker)
从 docker run 升级到 docker compose 是生产化的第一步。
原始的 docker run(仅适合测试) :
bash
docker run --gpus all -p 8000:8000 \
--name vllm-openai \
--shm-size=2g \
vllm/vllm-openai:latest \
--model /models/your-model \
--max-num-seqs 128
生产级 docker-compose.yml :
yaml
version: '3.8'
services:
vllm:
image: vllm/vllm-openai:latest
container_name: vllm-prod
restart: unless-stopped
ports:
- "8000:8000"
volumes:
- /data/models:/models # 模型持久化存储
- /data/logs:/logs # 日志持久化
shm_size: 2g
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
environment:
- CUDA_VISIBLE_DEVICES=0,1,2,3 # 指定使用哪些 GPU
- VLLM_LOGGING_LEVEL=INFO
command: >
--model /models/your-model
--tensor-parallel-size 4
--gpu-memory-utilization 0.85
--max-num-seqs 128
--max-model-len 8192
--dtype bfloat16
--port 8000
启动命令:
bash
docker compose up -d
docker compose logs -f # 查看日志
docker compose down # 停止服务
5.2 多卡部署(张量并行)
NVLink
PCIe(普通服务器默认通道):城市普通主干道,CPU、硬盘、所有显卡共用一条路,车多就堵车、速度慢;
NVLink 是英伟达专用高速数据线 / 互联通道,专门用来让多张 GPU 之间直接传数据,绕开主板普通 PCIe 通道,速度是普通主板通道的7~14 倍,延迟极低
NVLink 的物理形态是 有线的 电信号 传输。
例子 ------ 多卡部署,张量并行
当模型参数量超过单卡显存上限、单张显卡装不下完整权重+KV缓存时,需要开启张量并行,把模型权重拆分到多张GPU共同加载推理。
硬件要求:
多卡之间必须具备NVLink高速互联通道,否则多卡通信延迟极高,推理速度暴跌。
示例场景:
vllm serve 多卡启动命令, Qwen2-7B,2张GPU张量并行。
重点强调: 同一台服务器(一台电脑)里面插 2 张 GPU,不是两台机器。
张量并行(--tensor-parallel-size)的硬性限制:
- vLLM 的张量并行只支持单机内多卡,
- 所有 GPU 必须在同一台物理服务器上,共享主板、内存、NVLink 通道。
核心参数说明:
--tensor-parallel-size N:开启张量并行,N代表使用几张显卡拆分模型
- N必须等于实际启用GPU数量,如2卡填2、4卡填4
- 显卡序号由环境变量
CUDA_VISIBLE_DEVICES控制
bash
# 指定只用0、1两张显卡
export CUDA_VISIBLE_DEVICES=0,1
vllm serve "/root/autodl-tmp/Qwen2-7B-Instruct" \
--tensor-parallel-size 2 \
--host 0.0.0.0 \
--port 8001 \
--max-model-len 8192 \
--gpu-memory-utilization 0.85 \
--trust-remote-code
说明:
- 张量并行仅支持单机多卡,跨服务器多机拆分要用流水线并行/分布式并行;
- 无NVLink普通PCIe多卡不建议开TP,推理延迟会翻倍;
tensor-parallel-size数值不能超过可用GPU总数,否则启动直接报错;- LoRA场景同样兼容张量并行,只需保留原有
--enable-lora系列参数不变。
5.3 Kubernetes 部署(生产级标准)
Kubernetes 是生产环境部署的标准方案。核心思路:将 vLLM 部署为 Deployment,放在 ClusterIP Service 后面,这样副本数和节点数可以独立扩展。
Step 1:确保 Kubernetes 集群支持 GPU
需要安装 NVIDIA Device Plugin,它是一个 DaemonSet,会向集群报告 nvidia.com/gpu 资源。
Step 2:部署 vLLM Deployment
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-deployment
labels:
app: vllm
spec:
replicas: 2
selector:
matchLabels:
app: vllm
template:
metadata:
labels:
app: vllm
spec:
containers:
- name: vllm
image: vllm/vllm-openai:latest
args:
- "--model"
- "/models/your-model"
- "--tensor-parallel-size"
- "1"
- "--gpu-memory-utilization"
- "0.85"
- "--max-num-seqs"
- "128"
ports:
- containerPort: 8000
resources:
limits:
nvidia.com/gpu: 1 # 每个 Pod 请求 1 张 GPU
requests:
nvidia.com/gpu: 1
volumeMounts:
- name: model-storage
mountPath: /models
volumes:
- name: model-storage
persistentVolumeClaim:
claimName: model-pvc
Step 3:创建 Service
yaml
apiVersion: v1
kind: Service
metadata:
name: vllm-service
spec:
selector:
app: vllm
ports:
- port: 8000
targetPort: 8000
type: ClusterIP
Step 4:配置自动扩缩容(KEDA)
使用 KEDA 根据 vLLM 的请求队列深度自动扩缩容:
yaml
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
name: vllm-scaler
spec:
scaleTargetRef:
name: vllm-deployment
triggers:
- type: prometheus
metadata:
serverAddress: http://prometheus:9090
metricName: vllm_num_requests_waiting
threshold: '10'
query: vllm:num_requests_waiting
vLLM 原生暴露 /metrics 端点,提供 Prometheus 格式的监控数据。关键指标包括:
vllm:num_requests_waiting:等待队列长度(扩缩容依据)vllm:num_requests_running:正在处理的请求数- TTFT(Time-To-First-Token):首 token 延迟
- Prefix cache hit rate:前缀缓存命中率
5.4 负载均衡(多实例部署)
当单实例无法承载流量时,需要启动多个 vLLM 实例并用负载均衡器分发请求。
使用 Nginx 做负载均衡:
nginx
upstream vllm_backend {
server 192.168.1.10:8000;
server 192.168.1.11:8000;
server 192.168.1.12:8000;
}
server {
listen 80;
location / {
proxy_pass http://vllm_backend;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
更高级的方案可以使用支持路由策略的网关(如 round_robin、least_loaded、latency_based)。
5.5 监控与告警
Prometheus 指标采集 :vLLM 启动后自动在 /metrics 端点暴露指标。
Grafana 仪表板:vLLM 官方提供了 Grafana 仪表板配置(JSON 格式),要求 Grafana 8.0+。
需要重点监控的指标:
- GPU 利用率:是否充分利用了硬件
- 请求队列深度:是否即将过载,触发扩容
- TTFT 和 ITL:用户体验的核心指标
- 缓存命中率:前缀缓存是否生效
- 错误率:4xx/5xx 响应比例
第六部分:量化方案选型指南
量化是用有限显存跑更大模型的核心手段。vLLM 支持多种量化方案,各有取舍。
6.1 量化方案对比
| 量化方案 | 精度 | 显存节省 | 速度损失 | 效果损失 | 适用硬件 | 推荐场景 |
|---|---|---|---|---|---|---|
| FP16/BF16 | 16位浮点 | 基准 | 基准 | 无 | 全系列 | 对效果要求极高 |
| FP8 | 8位浮点 | ~50% | 极小(甚至更快) | 几乎不可察 | Hopper/Ada(W8A8)Ampere(W8A16) | 生产首选 |
| AWQ | 4位整型 | ~75% | 较小 | 轻微 | 全系列 NVIDIA | 大模型单卡部署 |
| GPTQ | 4位整型 | ~75% | 中等 | 轻微 | 全系列 NVIDIA | 兼容旧模型 |
| INT8 | 8位整型 | ~50% | 较大 | 较明显 | 全系列 | 已不推荐 |
6.2 FP8:当前最优解
FP8 是目前综合表现最好的量化方案,尤其在新一代显卡上(RTX 40 系、H100、L40S)有硬件加速。
FP8 两种模式:
- W8A8:权重和激活都是 FP8,有硬件加速,速度最快。需 Hopper/Ada 架构(算力 ≥ 8.9)
- W8A16:仅权重 FP8,激活 FP16。Ampere 架构也能用(A100、A10、3090)
启用 FP8:
bash
python -m vllm.entrypoints.openai.api_server \
--model meta-llama/Meta-Llama-3.1-8B-Instruct \
--quantization fp8 \
--gpu-memory-utilization 0.90
FP8 KV Cache :
还可以单独把 KV Cache 量化为 FP8,进一步省显存:
bash
python -m vllm.entrypoints.openai.api_server \
--model Qwen/Qwen2.5-14B-Instruct \
--kv-cache-dtype fp8_e5m2 \
--max-model-len 32768
效果:KV Cache 占用减半,支持更长上下文或更多并发,精度损失极小
6.3 AWQ / GPTQ:4bit 量化
如果要在 24GB 显存上跑 70B 模型,就需要 4bit 量化。
AWQ 示例:
bash
python -m vllm.entrypoints.openai.api_server \
--model TheBloke/Llama-3.1-70B-Instruct-AWQ \
--quantization awq \
--tensor-parallel-size 2 \
--gpu-memory-utilization 0.9
选型建议:
- 新部署优先选 FP8,综合性价比最高
- 必须 4bit 时优先选 AWQ,性能优于 GPTQ
- GPTQ 仅用于兼容存量模型文件
第七部分:生产监控与运维
7.1 健康检查
vLLM 提供 /health 端点,返回 200 表示引擎正常运行。
Kubernetes 探针配置示例:
yaml
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 300 # 模型加载慢,延迟检查
periodSeconds: 30
timeoutSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 60
periodSeconds: 10
7.2 Prometheus 指标
vLLM 内置 Prometheus 指标导出,访问 /metrics 端点即可获取。
核心监控指标:
| 指标名 | 含义 | 告警阈值建议 |
|---|---|---|
vllm:num_requests_running |
当前运行中的请求数 | 持续接近 max-num-seqs |
vllm:num_requests_waiting |
等待队列长度 | 持续 > 0 且增长 |
vllm:gpu_cache_usage_perc |
KV Cache 使用率 | > 90% 持续告警 |
vllm:avg_generation_throughput_toks_per_s |
生成吞吐量(token/s) | 低于基线 30% |
vllm:time_to_first_token_seconds |
首 token 延迟 | P95 > 2s 告警 |
Prometheus 抓取配置:
yaml
scrape_configs:
- job_name: 'vllm'
static_configs:
- targets: ['vllm-server:8000']
metrics_path: '/metrics'
scrape_interval: 15s
7.3 关键指标解读
- 等待队列持续增长:说明吞吐量不足,需要扩容或优化参数
- KV Cache 使用率接近 100%:显存饱和,新请求会抢占旧请求的缓存,导致颠簸
- 首 token 延迟突增:可能是预填充阶段遇到超长输入,可开启分块预填充
7.4 日志管理
vLLM 默认输出到 stdout。生产环境建议:
- Docker 部署使用日志驱动(如 json-file + logrotate)
- 集中收集到 ELK / Loki 等日志系统
- 关闭请求日志(
--disable-log-requests),避免高并发下日志量爆炸
bash
# 生产环境建议关闭请求级别日志
--disable-log-requests
7.5 压测工具推荐
- vllm-bench:vLLM 自带的基准测试工具
- llm-bench:专门的 LLM 推理压测工具
- apirise:通用 API 压测,支持 SSE 流式
简单压测示例:
bash
# 使用 vLLM 自带的 benchmark
python -m vllm.benchmarks.benchmark_throughput \
--model Qwen/Qwen2.5-7B-Instruct \
--dataset sharegpt \
--num-prompts 100
写在最后
vLLM 是一个持续快速迭代的项目,每个版本都会带来大量性能提升和新特性。核心原理和大部分参数是通用的,但具体细节可能随版本变化。
学习 vLLM 的最佳路径:
- 先跑通一个简单服务,建立直观认识
- 深入理解 PagedAttention 原理,建立正确的心智模型
- 动手调参压测,在实践中理解每个参数的影响
- 结合业务场景设计部署架构
记住:没有最优配置,只有最适合业务场景的配置。高吞吐和低延迟往往不可兼得,长上下文和高并发也存在权衡。理解原理,才能根据实际需求做出正确的取舍。