/metrics 全家桶
vLLM 启动后访问 http://host:8000/metrics(Prometheus 格式)。核心指标分四类:
1. 吞吐与延迟
| 指标 | 含义 | 健康区间 |
|---|---|---|
vllm:time_to_first_token_seconds | TTFT 直方图 | 聊天 p95 < 500ms |
vllm:time_per_output_token_seconds | TPOT 直方图 | bf16 70B < 30ms |
vllm:e2e_request_latency_seconds | 端到端请求延迟 | 因输出长度而异 |
vllm:prompt_tokens_total | 累计 prompt token 数 | — |
vllm:generation_tokens_total | 累计生成 token 数 | — |
2. 调度状态
| 指标 | 含义 | 告警阈值 |
|---|---|---|
vllm:num_requests_running | 正在 decode 的序列数 | 持续 = max-num-seqs 说明满载 |
vllm:num_requests_waiting | 排队等 prefill 的请求数 | > 10 就要加容量 |
vllm:num_requests_swapped | 被 swap 到 CPU 的序列数 | > 0 持续就说明池子小 |
vllm:num_preemptions_total | 累计 preemption 次数 | 增长快 = 要加 GPU / 减并发 |
3. KV cache 使用率
| 指标 | 含义 | 告警阈值 |
|---|---|---|
vllm:gpu_cache_usage_perc | GPU KV 池使用率 | 持续 > 90% 要扩容 |
vllm:cpu_cache_usage_perc | CPU swap 池使用率 | > 0 = 有溢出 |
vllm:gpu_prefix_cache_hit_rate | 前缀缓存命中率 | 多轮对话 > 40% 算正常 |
4. 投机解码 / LoRA(按特性)
| 指标 | 含义 |
|---|---|
vllm:spec_decode_draft_acceptance_rate | 草稿接受率 |
vllm:spec_decode_system_efficiency | 投机解码系统效率 |
vllm:lora_requests_total | 按 lora_name 分组的请求数 |
Grafana 看板最小集合
用 Prometheus scrape vLLM,Grafana 导入以下 4 个 Panel 就能覆盖 80% 排障场景:
- Panel 1 - 延迟直方图:
histogram_quantile(0.95, rate(vllm:time_to_first_token_seconds_bucket[5m]))和同样的 TPOT 画两条线 - Panel 2 - 吞吐:
rate(vllm:generation_tokens_total[1m])看每秒输出 token 数 - Panel 3 - 队列深度:
vllm:num_requests_waiting+vllm:num_requests_running叠加堆积图 - Panel 4 - KV 压力:
vllm:gpu_cache_usage_perc折线 +rate(vllm:num_preemptions_total[5m])柱状图
# prometheus.yml 片段 scrape_configs: - job_name: 'vllm' scrape_interval: 5s static_configs: - targets: ['vllm-host:8000'] metrics_path: '/metrics'
benchmark 压测:用官方脚本
vLLM 自带 benchmark_serving.py,能生成 Poisson 到达的合成负载:
# 准备 ShareGPT 数据集 wget https://huggingface.co/datasets/anon8231489123/ShareGPT_Vicuna_unfiltered/resolve/main/ShareGPT_V3_unfiltered_cleaned_split.json # 起服务(另一终端) vllm serve meta-llama/Llama-3-8B-Instruct # 压测 python -m vllm.entrypoints.openai.api_server.benchmark \ --backend openai \ --base-url http://localhost:8000 \ --model meta-llama/Llama-3-8B-Instruct \ --dataset ShareGPT_V3_unfiltered_cleaned_split.json \ --num-prompts 1000 \ --request-rate 20 # QPS
输出长这样:
Successful requests: 1000 Benchmark duration: 50.12 s Total input tokens: 234567 Total generated tokens: 145234 Request throughput: 19.95 req/s Input token throughput: 4680 tok/s Output token throughput: 2897 tok/s ─── Time to First Token ─────────────── Mean TTFT: 120 ms Median TTFT: 95 ms P99 TTFT: 480 ms ─── Time per Output Token ───────────── Mean TPOT: 15 ms Median TPOT: 13 ms P99 TPOT: 45 ms
常见性能问题速查
num_requests_waiting,开 --enable-chunked-prefill,必要时减 --max-model-len。num_requests_running,降 --max-num-seqs,或开 KV FP8 腾空间。--enable-chunked-prefill(0.6+ 默认开),调大 --max-num-batched-tokens。--gpu-memory-utilization 以外先量化(AWQ),再开 --kv-cache-dtype fp8。nvidia-smi topo -m,没 NVLink 不要 TP;或通信环境变量没配,设 NCCL_IB_DISABLE=0 NCCL_SOCKET_IFNAME=...。--enable-prefix-caching,多轮对话 TTFT 立刻降。几个被忽视的调优杠杆
1. --scheduler-delay-factor
默认 0,调度器来一个请求立刻处理。设成 0.5 让它等一小段(约当前步时间的 50%)聚合更多 prefill 一起做,吞吐↑ TTFT↑。夜间批量任务很香。
2. --swap-space
默认 4GB(CPU swap)。如果你的机器 RAM 富裕(256GB+),设成 64 能扛住更大并发波峰。但 swap 回来要重算 attention,看 num_requests_swapped 长期 > 0 说明你真正缺的是 GPU 不是 swap。
3. --enforce-eager
关掉 CUDA Graph 捕获。默认 vLLM 会在启动时 warmup 一堆 graph 加速 decode,首启动慢 30 秒。调试时加 --enforce-eager 更快但运行时慢 5-10%,生产一定关掉(不加这个参数)。
4. VLLM_USE_V1 环境变量
vLLM 0.6.3+ 有新调度器 V1(重写过,吞吐更高,尤其大 batch)。设 VLLM_USE_V1=1 启用。
日志怎么读
INFO Avg prompt throughput: 1234.5 tokens/s,
Avg generation throughput: 567.8 tokens/s,
Running: 42 reqs,
Swapped: 0 reqs,
Pending: 3 reqs,
GPU KV cache usage: 67.3%,
CPU KV cache usage: 0.0%
这是 vLLM 每 10 秒打一次的摘要行,生产上拿它做 alerting:
Swapped > 0持续 5 分钟 → 加 GPU 或降并发GPU KV cache usage > 90%持续 → 扩容信号Pending > 10持续 → TTFT 快要炸了generation_throughput异常掉 → 多半是 batch 被小请求填满了,检查客户端 max_tokens 配置
Profiling:深挖单请求
Prometheus 看的是聚合,想看单请求里每个 layer 耗时多少,用 Nsight Systems:
# 启动前 export export VLLM_TORCH_PROFILER_DIR=/tmp/vllm-prof vllm serve meta-llama/Llama-3-8B-Instruct # 触发 profile(其他终端) curl -X POST http://localhost:8000/start_profile # 发几个测试请求 curl -X POST http://localhost:8000/stop_profile # 用 Nsight 打开 /tmp/vllm-prof/*.json
能看到每次 forward 的 attention kernel / FFN / all-reduce 各占多少时间,针对性优化。
容量规划经验公式
并发上限 ≈ (KV 池 token 数) / (平均单请求 KV token 数) 例:A100-80G, Llama-3-8B, max-model-len=8192 KV 池 = 56GB → ~11 万 token 假设平均 prompt 500 + output 300 = 800 token/请求 理论并发 = 110000 / 800 ≈ 137 并发 再留 30% buffer 应对突发: 实际 --max-num-seqs 建议设 100
上线前用这公式估容量,压测对齐,就不会上线第一天就炸。
本章小结
- 生产 vLLM 必接 Prometheus,四大类指标:延迟 / 调度 / KV / 特性
- Grafana 最小看板 4 个 panel:延迟分位、吞吐、队列、KV 压力
- 症状→根因速查表:TTFT 问题 vs TPOT 问题完全不同调法
- benchmark_serving.py + ShareGPT 压测复现线上场景
- 日志每 10 秒一行摘要,把 Swapped / Pending / KV% 做成告警
- Nsight Systems 单请求 profile,找 kernel 级瓶颈