vLLM 是开源推理引擎,它把 PagedAttention 从研究论文变成了生产环境中服务开放权重大模型的常用方案。它原生兼容 OpenAI API,可以在单张 GPU 上批量处理数千个请求,支持跨多 GPU 的张量并行,并提供 FP8、AWQ、GPTQ、INT4 等量化方式,而且通常能在新模型发布当天开始运行。
本教程从一台装有 NVIDIA GPU 的干净 Linux 主机开始,最终搭建一个经过加固、带监控、前置 TLS 的 vLLM 服务。多数安装指南止步于 pip install vllm 和一次 curl,那只能得到演示环境,不是服务。完整部署还需要 hardened systemd 单元、支持 SSE 流式输出和 API 密钥限流的 nginx、自动续期的 Let's Encrypt TLS、多租户密钥网关、带真实告警规则的 Prometheus/Grafana,以及有意义的性能调优与实测数据。
本文终端输出和基准测试在 2026 年 5 月使用 vLLM 0.20.1、Ubuntu 24.04 LTS、NVIDIA RTX 4090(24 GB 显存)、驱动 580.95.05 和 CUDA 13.0 采集,指南在 2026 年 11 月重新审核。
最终架构
完成后,服务器会通过 https://vllm.example.com/v1/chat/completions 提供 OpenAI 兼容接口,以 systemd 服务运行并在失败时重启;nginx 负责 TLS 和按密钥限流;Prometheus 指标只在私有端口暴露;Grafana 展示队列深度、KV 缓存压力和首 token 延迟,并配置告警。
客户端 ──HTTPS──► nginx(TLS、限流、认证)──HTTP──► vllm.service(systemd)──CUDA──► GPU
│
└──/metrics──► Prometheus ──► Grafana
单 GPU 主机已经可以为小团队或内部工具提供可信的 LLM 端点。需要横向扩展时,可以在 nginx 后增加副本;需要纵向扩展时,可以增加 GPU 并使用张量并行。
硬件与操作系统要求
vLLM 以 GPU 为主。计算能力必须为 7.0 或更高,覆盖 Volta(V100)之后的 NVIDIA 显卡。实际起点通常是 Ampere 消费级显卡,例如 RTX 30 系列。
粗略估算:FP16 每个参数约 2 字节,FP8/INT8 约 1 字节,INT4 约半字节,再为 KV 缓存增加 10% 到 30%;长上下文还要更多。70B FP16 模型仅权重就约 140 GB,无法放入单张消费级 GPU,通常要使用两张 H100 做张量并行,或降到 FP8/INT4。
Ubuntu 24.04 LTS 是主要支持版本,Ubuntu 22.04 LTS 也可用。RHEL 9、Rocky Linux 9、AlmaLinux 9 同样支持,主要区别是软件包管理器由 apt 改为 dnf,以及 NVIDIA 驱动来源不同。磁盘至少准备 200 GB:一个大模型的 Hugging Face 缓存就可能达到 50 GB,并应保留两到三个模型的空间。
安装 NVIDIA 驱动与 CUDA
vLLM 的 PyTorch wheel 会携带 CUDA 运行时,因此主机只需安装 NVIDIA 内核驱动,不必安装完整 CUDA Toolkit。vLLM 0.20.x 对 CUDA 12.4 wheel 的最低驱动为 550,对默认提供的 CUDA 12.8/12.9/13.0 wheel 为 570。驱动过旧时引擎仍可能加载,但首个请求会出现难以理解的 CUBLAS_STATUS_NOT_INITIALIZED。
Ubuntu 无头服务器建议安装驱动元包:
sudo apt update
sudo ubuntu-drivers devices
sudo apt install -y nvidia-driver-570-server
sudo reboot
ubuntu-drivers devices 会列出推荐版本。如果推荐版本比 570 新,就安装它。新装 Ubuntu 24.04 时,570-server 分支是稳定选择;Blackwell 如需更新驱动,可通过 ppa:graphics-drivers/ppa 获取 575 或 580。
Rocky Linux / AlmaLinux 9 先启用 NVIDIA CUDA 仓库,再安装开放内核模块。Hopper 和 Blackwell 必须使用开放模块,Ada 与 Ampere 也可以正常使用:
sudo dnf config-manager --add-repo https://developer.download.nvidia.com/compute/cuda/repos/rhel9/x86_64/cuda-rhel9.repo
sudo dnf module install -y nvidia-driver:open-dkms
sudo reboot
重启后确认驱动和 GPU:
nvidia-smi
示例输出:
+-----------------------------------------------------------------------------------------+
| NVIDIA-SMI 580.95.05 Driver Version: 580.95.05 CUDA Version: 13.0 |
+-----------------------------------------+------------------------+----------------------+
| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
|=========================================+========================+======================|
| 0 NVIDIA GeForce RTX 4090 On | 00000000:C2:00.0 Off | Off |
| 60% 31C P8 33W / 450W | 1MiB / 24564MiB | 0% Default |
+-----------------------------------------+------------------------+----------------------+
持久模式可以缩短每次冷启动建立 CUDA 上下文的时间。启用方式:
sudo systemctl enable --now nvidia-persistenced
安装 vLLM
vLLM 0.20.x 推荐使用 uv。它会通过 --torch-backend=auto 自动选择与 CUDA 匹配的 PyTorch wheel,安装速度也明显快于 pip。以下流程创建独立系统用户,并把整套环境放在 /opt/vllm,避免污染系统 Python:
sudo useradd -r -m -d /opt/vllm -s /bin/false vllm
sudo apt install -y python3-venv curl ca-certificates
curl -LsSf https://astral.sh/uv/install.sh | sudo -u vllm sh
sudo -u vllm /opt/vllm/.local/bin/uv venv /opt/vllm/.venv --python 3.12 --seed
sudo -u vllm /opt/vllm/.local/bin/uv pip install \
--python /opt/vllm/.venv/bin/python vllm --torch-backend=auto
安装内容包括匹配 CUDA 的 PyTorch、FlashAttention、xFormers、vLLM kernels 和 OpenAI 兼容服务器。输出末尾示例:
+ torch==2.11.0+cu130
+ torchaudio==2.11.0+cu130
+ torchvision==0.26.0+cu130
+ tokenizers==0.22.2
+ transformers==5.8.0
+ triton==3.6.0
+ vllm==0.20.1
+ xgrammar==0.2.0
real 1m37.994s
确认版本:
/opt/vllm/.venv/bin/vllm --version
应返回:
0.20.1
如果使用 Docker,项目提供 vllm/vllm-openai 镜像,例如 v0.20.1-cu130-ubuntu2404。应固定版本标签,不要使用 latest。需要内核隔离或同机多套 LLM 栈时可选 Docker;单机专用服务器且希望攻击面最小时,裸机安装更合适。
精简系统镜像可能缺少 Triton JIT 所需的 Python 头文件,错误通常是在 /tmp/tmpXXXX/cuda_utils.c 中出现 Python.h: No such file or directory。安装以下软件包即可:
sudo apt install -y python3-dev build-essential
首次运行 vllm serve
先手动启动一次,确认模型加载、API 绑定和 GPU 使用正常。本教程使用 Qwen/Qwen2.5-7B-Instruct,它是开放权重模型,不需要 Hugging Face token,FP16 在 24 GB 显卡上运行良好,并且兼容 vLLM 的工具调用解析器。
预下载权重,避免网络错误与 CUDA 初始化日志混在一起:
sudo -u vllm /opt/vllm/.venv/bin/pip install --quiet huggingface_hub
sudo -u vllm /opt/vllm/.venv/bin/huggingface-cli download Qwen/Qwen2.5-7B-Instruct
受限模型可在命令前加 HF_TOKEN=hf_xxx,或由 vllm 用户执行一次 huggingface-cli login。模型下载到本地后,vLLM 不再需要该 token。
手动测试只绑定到 127.0.0.1:
sudo -u vllm /opt/vllm/.venv/bin/vllm serve Qwen/Qwen2.5-7B-Instruct \
--host 127.0.0.1 --port 8000 \
--api-key sk-cfg-demo-key \
--gpu-memory-utilization 0.90 \
--max-model-len 16384 \
--max-num-seqs 128 \
--served-model-name qwen2.5-7b
快速磁盘首次启动约 30 到 90 秒。vLLM 会加载权重、分配 KV 缓存块、从 batch size 1 到 --max-num-seqs 捕获 CUDA graphs,最后启动 API。关键日志如下:
INFO [core.py:109] Initializing a V1 LLM engine (v0.20.1) with config: model='Qwen/Qwen2.5-7B-Instruct'
INFO [cuda.py:368] Using FLASH_ATTN attention backend out of potential backends: ['FLASH_ATTN', 'FLASHINFER', 'TRITON_ATTN', 'FLEX_ATTENTION'].
INFO [flash_attn.py:646] Using FlashAttention version 2
INFO [gpu_model_runner.py:4879] Model loading took 14.25 GiB memory and 3.654477 seconds
INFO [gpu_worker.py:440] Available KV cache memory: 5.41 GiB
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:8000
14.25 GiB 是 bfloat16 权重占用的显存,5.41 GiB 是扣除激活和开销后可用的 KV 缓存。把 --gpu-memory-utilization 提高到 0.95 可以再回收一到两 GiB,但长期运行和内存碎片可能触发 OOM。

查看模型列表:
curl -s http://127.0.0.1:8000/v1/models \
-H "Authorization: Bearer sk-cfg-demo-key" | python3 -m json.tool
响应中的模型别名与 --served-model-name 一致:
{
"object": "list",
"data": [
{
"id": "qwen2.5-7b",
"object": "model",
"created": 1778106064,
"owned_by": "vllm",
"root": "Qwen/Qwen2.5-7B-Instruct",
"max_model_len": 16384,
"permission": [
{
"allow_sampling": true,
"allow_logprobs": true,
"allow_view": true,
"allow_fine_tuning": false
}
]
}
]
}
发送流式聊天请求,同时验证 SSE 行为:
curl -s -N http://127.0.0.1:8000/v1/chat/completions \
-H "Authorization: Bearer sk-cfg-demo-key" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen2.5-7b",
"stream": true,
"messages": [{"role": "user", "content": "In one sentence, what is PagedAttention?"}]
}' | head -20
响应按 data: 分块逐 token 到达:
data: {"id":"chatcmpl-84311d23","object":"chat.completion.chunk","model":"qwen2.5-7b","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}
data: {"id":"chatcmpl-84311d23","object":"chat.completion.chunk","model":"qwen2.5-7b","choices":[{"index":0,"delta":{"content":"P"},"finish_reason":null}]}
data: {"id":"chatcmpl-84311d23","object":"chat.completion.chunk","model":"qwen2.5-7b","choices":[{"index":0,"delta":{"content":"aged"},"finish_reason":null}]}
data: {"id":"chatcmpl-84311d23","object":"chat.completion.chunk","model":"qwen2.5-7b","choices":[{"index":0,"delta":{"content":"Attention"},"finish_reason":null}]}
data: {"id":"chatcmpl-84311d23","object":"chat.completion.chunk","model":"qwen2.5-7b","choices":[{"index":0,"delta":{"content":" is"},"finish_reason":null}]}
data: {"id":"chatcmpl-84311d23","object":"chat.completion.chunk","model":"qwen2.5-7b","choices":[{"index":0,"delta":{"content":" an"},"finish_reason":null}]}
data: {"id":"chatcmpl-84311d23","object":"chat.completion.chunk","model":"qwen2.5-7b","choices":[{"index":0,"delta":{"content":" efficient"},"finish_reason":null}]}
...
data: [DONE]
成功后按 Ctrl+C 停止,下一步改为 systemd 服务。

另开终端运行 nvidia-smi,可以看到 VLLM::EngineCore 工作进程。测试中功耗约 78 W、显存使用约 21.4 GiB。

--gpu-memory-utilization 降到 0.85 留出余量;触顶会导致请求抢占并产生延迟尖峰。
用加固的 systemd 服务运行 vLLM
在 tmux 中运行 vllm serve 只适合测试。生产部署需要失败重启、降低权限、隔离文件系统,并从权限严格的文件读取密钥,避免 API key 出现在 ps。
创建环境文件:
sudo install -d -m 0755 -o root -g root /etc/vllm
sudo install -d -m 0755 -o vllm -g vllm /var/log/vllm
sudo tee /etc/vllm/env >/dev/null <<'EOF'
HF_HOME=/opt/vllm/hf-cache
HF_HUB_OFFLINE=1
VLLM_API_KEY=sk-cfg-please-rotate-me
EOF
sudo chown vllm:vllm /etc/vllm/env
sudo chmod 600 /etc/vllm/env
模型预下载后设置 HF_HUB_OFFLINE=1,可以防止每次启动访问 Hugging Face,也能避免上游故障影响启动。
创建 /etc/systemd/system/vllm.service:
[Unit]
Description=vLLM OpenAI-compatible inference server
After=network-online.target nvidia-persistenced.service
Wants=network-online.target
[Service]
Type=simple
User=vllm
Group=vllm
EnvironmentFile=/etc/vllm/env
ExecStart=/opt/vllm/.venv/bin/vllm serve Qwen/Qwen2.5-7B-Instruct \
--host 127.0.0.1 --port 8000 \
--api-key ${VLLM_API_KEY} \
--served-model-name qwen2.5-7b \
--gpu-memory-utilization 0.90 \
--max-model-len 16384 \
--max-num-seqs 128 \
--enable-prefix-caching
Restart=on-failure
RestartSec=10
TimeoutStartSec=600
TimeoutStopSec=60
LimitNOFILE=1048576
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/opt/vllm /var/log/vllm
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
StandardOutput=journal
StandardError=journal
SyslogIdentifier=vllm
[Install]
WantedBy=multi-user.target
TimeoutStartSec=600 给大模型加载和 CUDA 图捕获留出最多十分钟。LimitNOFILE=1048576 提高并发流数量上限。严格文件系统隔离下,ReadWritePaths 是唯一可写区域。
启用服务:
sudo systemctl daemon-reload
sudo systemctl enable --now vllm
sudo systemctl status vllm --no-pager
查看日志:
sudo journalctl -u vllm -f
journald 会自动轮转。如需更长历史,可在 /etc/systemd/journald.conf 中设置 SystemMaxUse=2G 后重新加载。
使用 nginx 反向代理、TLS 与 SSE
安装 nginx 和 certbot:
sudo apt install -y nginx certbot python3-certbot-nginx
sudo systemctl enable --now nginx
Rocky Linux 9 从 EPEL 安装对应的 nginx、certbot、python3-certbot-nginx 包。设置域名和邮箱变量:
DOMAIN=vllm.example.com
EMAIL=admin@example.com
为该域名配置指向公网 IP 的 A 记录。certbot 的 HTTP-01 挑战需要公网能访问 80 端口;NAT 后或需要泛域名证书时,应改用 DNS-01 和相应的 DNS 插件。
开放防火墙:
sudo ufw allow 80,443/tcp
sudo ufw status
创建 /etc/nginx/sites-available/vllm:
limit_req_zone $http_authorization zone=per_key:10m rate=120r/m;
upstream vllm_backend {
server 127.0.0.1:8000;
keepalive 64;
}
server {
listen 80;
listen [::]:80;
server_name vllm.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name vllm.example.com;
# certbot fills these in:
# ssl_certificate /etc/letsencrypt/live/vllm.example.com/fullchain.pem;
# ssl_certificate_key /etc/letsencrypt/live/vllm.example.com/privkey.pem;
client_max_body_size 16M;
keepalive_timeout 75s;
location / {
limit_req zone=per_key burst=40 nodelay;
limit_req_status 429;
proxy_pass http://vllm_backend;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Connection "";
# Critical for SSE streaming
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
chunked_transfer_encoding on;
}
}
限流区域以 Authorization 头为键,每个 API key 每分钟 120 次、允许突发 40 次;匿名流量共用空键桶。proxy_buffering off 是保证流式响应的关键,否则 nginx 会缓存整个 SSE 响应,最终一次性返回。
启用配置并检查:
sudo ln -s /etc/nginx/sites-available/vllm /etc/nginx/sites-enabled/vllm
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx
申请证书:
sudo certbot --nginx -d "$DOMAIN" --non-interactive --agree-tos --redirect -m "$EMAIL"
测试自动续期:
sudo certbot renew --dry-run
验证公网流式请求:
curl -s -N "https://$DOMAIN/v1/chat/completions" \
-H "Authorization: Bearer sk-cfg-please-rotate-me" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen2.5-7b",
"stream": true,
"messages": [{"role": "user", "content": "List three production benefits of PagedAttention."}]
}'
data: 行应逐条出现。如果全部在末尾同时到达,检查当前启用的站点文件以及 /etc/nginx/conf.d/ 是否覆盖了 proxy_buffering。
使用 LiteLLM 提供多租户 API key
vLLM 的 --api-key 只接受一个共享密钥。第二个团队或应用需要访问时,就需要按密钥统计、预算和无需重启的轮换。LiteLLM 可以作为 vLLM 前的轻量代理,对外提供 OpenAI API,并补充多租户功能。
独立安装 LiteLLM:
sudo useradd -r -m -d /opt/litellm -s /bin/false litellm
sudo -u litellm /opt/vllm/.local/bin/uv venv /opt/litellm/.venv --python 3.12 --seed
sudo -u litellm /opt/vllm/.local/bin/uv pip install \
--python /opt/litellm/.venv/bin/python "litellm[proxy]"
创建 /etc/litellm/config.yaml:
model_list:
- model_name: qwen2.5-7b
litellm_params:
model: openai/qwen2.5-7b
api_base: http://127.0.0.1:8000/v1
api_key: sk-cfg-please-rotate-me
general_settings:
master_key: sk-litellm-master-rotate-me
database_url: sqlite:////opt/litellm/litellm.db
alerting: ["slack"]
litellm_settings:
drop_params: true
set_verbose: false
json_logs: true
request_timeout: 600
systemd 服务监听 4000 端口,加固方式与 vLLM 服务相同,只需把 ExecStart 改成:
ExecStart=/opt/litellm/.venv/bin/litellm --config /etc/litellm/config.yaml --port 4000 --host 127.0.0.1
将 nginx 的 upstream 指向 127.0.0.1:4000,然后生成团队密钥:
curl -s http://127.0.0.1:4000/key/generate \
-H "Authorization: Bearer sk-litellm-master-rotate-me" \
-H "Content-Type: application/json" \
-d '{
"models": ["qwen2.5-7b"],
"max_budget": 10,
"budget_duration": "30d",
"metadata": {"team": "platform"}
}' | python3 -m json.tool
LiteLLM 会记录每个密钥的请求数、token 数和等价成本,并在达到预算 80% 时触发 Slack 告警。
Prometheus、Grafana 与实用告警
vLLM 在 /metrics 暴露请求队列、迭代吞吐、KV 缓存使用率等指标。重点指标:
| 指标 | 含义 |
|---|---|
vllm:num_requests_running |
当前并发序列,达到 --max-num-seqs 后饱和 |
vllm:num_requests_waiting |
队列深度,持续大于 0 表示 CPU 或 GPU 已受限 |
vllm:kv_cache_usage_perc |
KV 缓存填充率,超过 95% 会开始抢占请求 |
vllm:time_to_first_token_seconds |
首 token 延迟直方图,p95 最接近用户感受 |
vllm:time_per_output_token_seconds |
token 间延迟,乘以输出 token 数可估算生成时间 |
vllm:prompt_tokens_total |
提示词 token 累计计数 |
vllm:generation_tokens_total |
输出 token 累计计数 |
vllm:prefix_cache_hits_total |
前缀缓存命中数,命中越高通常 TTFT 越低 |
指标与 API 共用端口和密钥,不应直接暴露公网。查询示例:
curl -s http://127.0.0.1:8000/metrics \
-H "Authorization: Bearer $VLLM_API_KEY" | grep '^vllm:' | head
输出示例:
vllm:num_requests_running{engine="0",model_name="qwen2.5-7b"} 0.0
vllm:num_requests_waiting{engine="0",model_name="qwen2.5-7b"} 0.0
vllm:kv_cache_usage_perc{engine="0",model_name="qwen2.5-7b"} 0.0
vllm:prefix_cache_queries_total{engine="0",model_name="qwen2.5-7b"} 39.0
vllm:prefix_cache_hits_total{engine="0",model_name="qwen2.5-7b"} 0.0
vllm:engine_sleep_state{engine="0",model_name="qwen2.5-7b",sleep_state="awake"} 1.0

使用 Docker Compose 运行 Prometheus 和 Grafana:
services:
prometheus:
image: prom/prometheus:latest
container_name: prometheus
network_mode: host
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- ./alerts.yml:/etc/prometheus/alerts.yml:ro
- prom-data:/prometheus
command:
- --config.file=/etc/prometheus/prometheus.yml
- --storage.tsdb.retention.time=30d
- --web.listen-address=127.0.0.1:9090
restart: unless-stopped
grafana:
image: grafana/grafana:latest
container_name: grafana
network_mode: host
environment:
- GF_SERVER_HTTP_ADDR=127.0.0.1
- GF_SERVER_HTTP_PORT=3000
- GF_SECURITY_ADMIN_PASSWORD__FILE=/run/secrets/grafana_admin
volumes:
- grafana-data:/var/lib/grafana
- ./grafana_admin:/run/secrets/grafana_admin:ro
restart: unless-stopped
volumes:
prom-data:
grafana-data:
Prometheus 配置:
global:
scrape_interval: 15s
evaluation_interval: 15s
rule_files:
- alerts.yml
scrape_configs:
- job_name: vllm
metrics_path: /metrics
authorization:
type: Bearer
credentials: sk-cfg-please-rotate-me
static_configs:
- targets: ['127.0.0.1:8000']
labels:
service: vllm
gpu: rtx-4090
- job_name: node
static_configs:
- targets: ['127.0.0.1:9100']
告警规则:
groups:
- name: vllm
interval: 30s
rules:
- alert: VllmQueueBacklog
expr: vllm:num_requests_waiting > 50
for: 5m
labels:
severity: warning
annotations:
summary: "vLLM queue backlog over 50 for 5 minutes on {{ $labels.gpu }}"
description: "Capacity is the bottleneck. Add a replica or raise --max-num-seqs."
- alert: VllmKvCachePressure
expr: vllm:kv_cache_usage_perc > 0.95
for: 2m
labels:
severity: warning
annotations:
summary: "KV cache > 95% on {{ $labels.gpu }}"
description: "Concurrent sequences are about to be preempted. Reduce --max-model-len or scale out."
- alert: VllmTtftHigh
expr: histogram_quantile(0.95, sum(rate(vllm:time_to_first_token_seconds_bucket[5m])) by (le, gpu)) > 2
for: 10m
labels:
severity: critical
annotations:
summary: "p95 TTFT > 2s on {{ $labels.gpu }}"
description: "User-visible latency degraded. Check GPU saturation, queue depth, and recent traffic spike."
启动监控栈:
cd /opt/observability
echo "$(openssl rand -hex 24)" | sudo tee grafana_admin >/dev/null
sudo chmod 600 grafana_admin
sudo docker compose up -d
sudo docker compose ps
在 Grafana 中添加 http://127.0.0.1:9090 数据源,再导入官方 vLLM 仪表盘 examples/observability/prometheus_grafana。
真正有效的性能调优
vLLM 有约四十个命令行参数,生产环境通常只需少数几个:
| 参数 | 默认值 | 作用 |
|---|---|---|
--gpu-memory-utilization |
0.90 | vLLM 启动时占用显存比例,OOM 时降低,想增加 KV 缓存可提到 0.95 |
--max-model-len |
模型最大值 | 上下文窗口,降低可释放更多 KV 块给并发 |
--max-num-seqs |
256 | 最大并发序列,提高吞吐但可能恶化 p99 TTFT |
--max-num-batched-tokens |
自动 | 每轮调度 token 预算,提高吞吐或降低首包延迟 |
--enable-prefix-caching |
开 | 复用相同前缀的 KV 缓存 |
--enable-chunked-prefill |
开 | 交错预填充和解码,让高负载下 TTFT 更稳定 |
--kv-cache-dtype |
自动 | 设为 fp8 可把 KV 缓存内存减半 |
--quantization |
无 | 单 GPU 运行 70B 可用 AWQ 或 FP8 |
--dtype |
自动 | Ampere 及以上建议 bfloat16 |
--tensor-parallel-size |
1 | 将模型切分到同机多张 GPU |
--enforce-eager |
关 | 关闭 CUDA 图捕获,只用于调试,会损失 10% 到 30% 吞吐 |
吞吐与延迟通过批调度互相制约:--max-num-batched-tokens 提高吞吐但会让新请求等待更久;--max-num-seqs 提高并发但每请求分到的 GPU 更少。调优顺序应是先保证 KV 缓存空间,再调并发,最后调批 token 数以优化 TTFT。
单张 RTX 4090 的基准结果
测试使用 vllm bench serve 回放 ShareGPT 风格提示词:
/opt/vllm/.venv/bin/vllm bench serve \
--backend openai-chat \
--base-url http://127.0.0.1:8000 \
--endpoint /v1/chat/completions \
--model qwen2.5-7b \
--tokenizer Qwen/Qwen2.5-7B-Instruct \
--dataset-name sharegpt \
--dataset-path /tmp/sharegpt.json \
--num-prompts 128 \
--max-concurrency 32 \
--request-rate 20 \
--api-key sk-cfg-please-rotate-me
并发 128 时,总吞吐超过 5,000 token/s,中位 TTFT 为 138 ms,中位 token 间延迟为 22 ms。

并发从 1 增加到 128 时,总吞吐从每秒 178 token 提升到超过 5,000 token,约为 30 倍;单请求吞吐则从每秒 61 token 降到 17 token。RTX 4090 在该模型和上下文下大约在 32 到 128 并发之间饱和,继续提高并发只会进入队列。
一次 c8 测试的 p99 TTFT 出现 5.3 秒尖峰,是长生成收尾时到达的单个异常请求;中位 TTFT 52 ms、p99 ITL 27 ms 更能代表稳定状态。只有单用户且无法批处理时,vLLM 无法充分利用 GPU,可考虑较小显卡上的 llama.cpp 或多个模型副本。
多 GPU 张量并行
70B FP16 模型权重约 140 GB。vLLM 可通过 --tensor-parallel-size N 把模型拆分到同机多张 GPU,只要求模型 hidden size 能被 N 整除,常见架构在 N 不超过 8 时都满足。
/opt/vllm/.venv/bin/vllm serve meta-llama/Llama-3.1-70B-Instruct \
--tensor-parallel-size 2 \
--gpu-memory-utilization 0.92 \
--max-model-len 8192 \
--quantization fp8
两张 H100 80GB 可舒适运行 70B FP8;两张 L40S 48GB 需要 INT4 或 AWQ。跨主机部署时,流水线并行通过 --pipeline-parallel-size 按节点切分,张量并行负责节点内切分。通常约定 tensor-parallel=每节点 GPU 数、pipeline-parallel=节点数。多主机还需要 Ray 和高速网络。
常见故障
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
首次请求出现 Python.h: No such file or directory |
Triton JIT 缺少 Python 头文件 | apt install python3-dev build-essential |
| 启动时 CUDA out of memory | KV 缓存超出可用显存 | 降低 --gpu-memory-utilization、减小 --max-model-len 或设置 --kv-cache-dtype fp8 |
CUDA error: no kernel image is available |
wheel 不包含当前 GPU 计算能力的 kernel | 使用匹配的镜像,或带 TORCH_CUDA_ARCH_LIST 从源码构建 |
huggingface-cli 下载返回 HTTP 401 |
受限模型缺少 token | 以 vllm 用户登录,或在 /etc/vllm/env 设置 HF_TOKEN |
| 流式响应一次性返回 | 代理缓冲开启 | nginx 配置 proxy_buffering off,检查 /etc/nginx/conf.d/ |
| 多 GPU 启动时 NCCL 卡住 | NCCL 版本不一致、网卡绑定或 P2P 问题 | 设置 NCCL_DEBUG=INFO、固定 NCCL_SOCKET_IFNAME,统一 NCCL 版本 |
| 首次请求超过 30 秒 | 冷引擎加载权重并捕获 CUDA 图 | 加入负载均衡前先用请求预热,并提高启动探针超时 |
| Hugging Face 下载很慢 | 匿名限流 | 即使模型公开也应设置 HF_TOKEN |
RuntimeError: Engine core initialization failed |
启动阶段异常的通用包装 | 在日志中继续向上查看真正的错误 |
vLLM 与其他推理引擎
| 引擎 | 最适合 | 取舍 |
|---|---|---|
| vLLM | NVIDIA 多租户生产、模型覆盖广、新模型支持快 | 冷启动较重,ROCm 支持落后 CUDA |
| HuggingFace TGI | HF 原生环境、Inferentia/Gaudi | 新模型支持慢于 vLLM,Rust+Python 双栈 |
| TensorRT-LLM + Triton | 全 NVIDIA、追求极致延迟 | 每个模型都需编译,运维复杂 |
| SGLang | Agent、结构化 JSON、共享前缀的 RAG | 社区较小,新模型支持较少 |
| llama.cpp / llama-server | 单流、CPU 回退、Apple Silicon | 持续批处理能力弱,不适合大量并发 |
| Ollama | 开发机、Mac、内部演示 | 底层是 llama.cpp,生产参数少 |
| LMDeploy | Qwen、InternLM、昇腾 | 西方社区较小,文档偏中文 |
SGLang 的 RadixAttention 会自动复用共享前缀的 KV 缓存,在 agent 和 RAG 负载上很有吸引力。对于共享 4 KB 系统提示词和 8 KB 固定文档的 RAG,SGLang 报告同硬件可获得 2 到 5 倍吞吐提升。普通聊天请求很少共享长前缀时,vLLM 仍然是稳妥选择。
后续方向
至此,单节点已具备 OpenAI 兼容 HTTPS 服务、失败重启、按 key 限流、指标和三条告警规则。后续可扩展为 nginx 后的多副本、基于 Ray 的多节点 70B 服务、使用 llm-d 的解耦预填充/解码,或 Kubernetes 部署。Kubernetes 需要 NVIDIA device plugin、GPU 节点池、模型缓存 PVC 和 KV 缓存感知路由,复杂度足以单独成篇。
模型选择可参考 Ollama 模型速查表;它覆盖 vLLM 可服务的同类模型,并按显存和质量说明取舍,可映射到 --max-num-seqs 与 --gpu-memory-utilization 调优。新参数和支持模型应以 vLLM 官方文档为准。










