一、vLLM 简介
1.1 什么是 vLLM?
vLLM 是目前业界最流行的高性能开源大模型推理框架。它不是用于“训练”模型的平台,而是专门用于“运行”已经训练好的大模型(如 GPT、Llama、Qwen 等)的加速引擎。
1.2 核心特性
定位 :解决大模型部署阶段显存占用高、吞吐量低、响应慢的问题。
性能 :在同等硬件条件下,vLLM 的吞吐量通常比传统的 Hugging Face Transformers 库高 2 到 24 倍。
1.3 核心技术
PagedAttention(核心创新)
- 痛点:传统 Attention 机制会预分配显存,导致大量碎片浪费(显存利用率通常低于 40%)。
- 方案:借鉴操作系统的“虚拟内存分页”技术,将 KV Cache 切分成小块(Page/Block),按需动态分配。这使得显存利用率可提升至 90% 以上。
连续批处理(Continuous Batching)
- 痛点:传统 Batching 必须等待一个 Batch 中最长的请求生成完毕,导致 GPU 出现空闲等待。
- 方案:实现细粒度的动态调度,一旦某个请求生成结束,立即插入新请求,保持 GPU 始终处于满载计算状态。
二、环境准备
2.1 硬件要求
-
GPU:NVIDIA GPU(推荐 A100/A10/4090/3090)。
- 显存提示:部署 Qwen2.5-7B-Instruct (bfloat16) 建议显存 ≥24GB。
-
CPU/内存:建议 16GB+ 系统内存。
2.2 软件要求
-
操作系统:Linux (Ubuntu 20.04/22.04 推荐)。
-
Python:3.9 - 3.12。
-
CUDA:关键点,推荐 CUDA 12.1 或 11.8。
- 检查命令:
nvcc --version
- 检查命令:
2.3 创建虚拟环境
conda create -n vllm python=3.10 -y
conda activate vllm
三、vLLM 安装
3.1 安装方式
# 安装 vLLM 稳定版 (会自动适配 CUDA 12.1 或 11.8)
pip install vllm
# 验证安装
python -c "import vllm; print(f'vLLM version: {vllm.__version__}')"
4.1 下载 Qwen 模型(推荐 SDK 方式)
修正点:直接 git clone 大文件极易失败且不支持断点续传。推荐使用 ModelScope SDK 下载。
-
安装下载工具
pip install modelscope -
执行下载脚本 创建一个 python 脚本
download_model.py:from modelscope import snapshot_download # 下载 Qwen2.5-7B-Instruct 到当前目录的 models 文件夹下 model_dir = snapshot_download( 'qwen/Qwen2.5-7B-Instruct', cache_dir='./models', revision='master' ) print(f"模型已下载至: {model_dir}") -
运行下载
python download_model.py
五、服务部署
5.1 启动 vLLM 服务
假设模型下载路径为 ./models/qwen/Qwen2.5-7B-Instruct。
vllm serve ./models/qwen/Qwen2.5-7B-Instruct \
--host 0.0.0.0 \
--port 8000 \
--tensor-parallel-size 1 \
--dtype bfloat16 \
--max-model-len 8192 \
--gpu-memory-utilization 0.95 \
--trust-remote-code
5.2 关键参数详解
--tensor-parallel-size 1:单卡设为 1;如果是双卡 4090 跑 7B 模型,依然设为 1(单卡足够),跑 72B 模型则设为 2 或 4。--max-model-len 8192:重要。Qwen2.5 支持 32k+,但在 24GB 显存下,设置过大会导致 OOM(显存溢出)。8192 是一个安全值,如果显存充足可尝试 16384。--gpu-memory-utilization 0.95:允许 vLLM 使用 95% 的 GPU 显存(预留 5% 给系统开销)。--trust-remote-code:部分新模型架构需要此参数信任执行代码。
六、部署后测试
6.1 基础连通性测试
# 健康检查
curl http://localhost:8000/health
6.2 OpenAI 兼容接口测试
vLLM 原生兼容 OpenAI API 格式,可直接调用:
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "./models/qwen/Qwen2.5-7B-Instruct",
"messages": [
{"role": "system", "content": "你是一个专业的AI助手。"},
{"role": "user", "content": "请解释一下什么是微服务架构?"}
],
"temperature": 0.7,
"max_tokens": 512
}'
(注意:model 字段需要填写启动服务时指定的模型路径名称,或者通过 curl http://localhost:8000/v1/models 查询准确名称)
6.3 压力与性能测试脚本
修正点:优化了并发统计逻辑,确保 P95 数据具有统计意义。
创建 benchmark.py:
import time
import threading
import numpy as np
from openai import OpenAI
# 配置
BASE_URL = "http://localhost:8000/v1"
API_KEY = "EMPTY"
MODEL_NAME = "./models/qwen/Qwen2.5-7B-Instruct" # 请确认与 v1/models 返回一致
CONCURRENT_REQUESTS = 20 # 并发数
TOTAL_TOKENS = 256 # 生成长度
client = OpenAI(base_url=BASE_URL, api_key=API_KEY)
def send_request(results):
start_time = time.time()
try:
client.chat.completions.create(
model=MODEL_NAME,
messages=[{"role": "user", "content": "请写一段关于人工智能未来的200字短文。"}],
max_tokens=TOTAL_TOKENS,
temperature=0.8
)
latency = time.time() - start_time
results.append(latency)
print(f"请求完成: {latency:.2f}s")
except Exception as e:
print(f"请求失败: {e}")
def run_benchmark():
threads = []
results = []
print(f"开始压测:并发数 {CONCURRENT_REQUESTS}...")
for _ in range(CONCURRENT_REQUESTS):
t = threading.Thread(target=send_request, args=(results,))
threads.append(t)
t.start()
for t in threads:
t.join()
if results:
avg = np.mean(results)
p95 = np.percentile(results, 95)
print(f"\n=== 测试结果 ===")
print(f"成功请求: {len(results)}")
print(f"平均延迟: {avg:.2f}s")
print(f"P95 延迟: {p95:.2f}s")
print(f"预估吞吐量 (QPS): {len(results) / max(results):.2f}")
if __name__ == "__main__":
run_benchmark()
七、监控与进阶优化
7.1 监控指标
vLLM 暴露了 Prometheus 格式的监控指标。
-
Endpoint:
http://localhost:8000/metrics -
关键指标:
vllm:num_requests_running:当前正在处理的请求数。vllm:gpu_cache_usage_perc:KV Cache 显存使用率(接近 100% 说明负载饱和)。
7.2 生产环境优化建议
-
启用量化(Quantization) :
- 显存不足时,推荐使用 AWQ 或 GPTQ 量化模型(如
Qwen2.5-7B-Instruct-AWQ)。 - 显存占用可减少约 50%,吞吐量提升显著。
- 启动命令增加:
--quantization awq。
- 显存不足时,推荐使用 AWQ 或 GPTQ 量化模型(如
-
KV Cache 优化:
- 如果输入文本极长(如文档分析),适当增加
--gpu-memory-utilization至 0.98(需谨慎,防 OOM)。 - 如果并发极高,适当减小
--max-model-len以腾出显存给 Batch Size。
- 如果输入文本极长(如文档分析),适当增加
八、Docker 部署方案(推荐)
使用 Docker 可以避免 CUDA 版本冲突。
8.1 编写 docker-compose.yml
version: '3.8'
services:
vllm:
image: vllm/vllm-openai:latest
container_name: vllm-service
runtime: nvidia
environment:
- HUGGING_FACE_HUB_TOKEN=your_token_if_needed
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
volumes:
# 映射宿主机模型目录到容器内的 /models
- ./models/qwen/Qwen2.5-7B-Instruct:/models/qwen:ro
# 显式指定容器内模型路径
command: >
--model /models/qwen
--host 0.0.0.0
--port 8000
--dtype bfloat16
--gpu-memory-utilization 0.95
--max-model-len 8192
ports:
- "8000:8000"
ipc: host # 必须配置,共享内存,防止多进程通信失败
restart: unless-stopped
8.2 启动与验证
docker-compose up -d
docker logs -f vllm-service
当看到日志输出 Uvicorn running on http://0.0.0.0:8000 时,即代表启动成功。
九、总结
通过 vLLM 部署 Qwen2.5 模型,我们实现了“高吞吐、低延迟”的推理服务。对于技术团队而言,重点关注以下三点以保证线上稳定性:
- 显存管理:合理设置
max-model-len和gpu-memory-utilization避免 OOM。 - 版本匹配:确保 CUDA、PyTorch 和 vLLM 版本兼容。
- 量化策略:资源受限时,优先选择 AWQ/GPTQ 量化模型而非硬抗 FP16。