性能指标与监控:吞吐量、延迟与GPU利用率的观测体系

vLLM 的吞吐稳定性保障,前提是建立一套可量化、可对比、可追踪的观测体系。如果只关注“服务是否报错”或“显存是否占满”,往往会在性能劣化发生数分钟甚至数小时后才发现问题。本节围绕吞吐量、延迟、GPU 利用率三类核心指标,讲解它们的定义、采集方式、关联分析方法,以及日志与监控工具的组合使用策略。

核心指标的定义与业务含义

在 vLLM 场景中,指标不能孤立理解。吞吐量回答“系统完成了多少工作”,延迟回答“每个请求等待了多久”,GPU 利用率回答“算力是否被有效消耗”。三者共同构成性能三角,任何单一指标都不能反映真实服务质量。

指标类别 常用单位 关键子指标 业务含义
吞吐量 req/s, tokens/s 输出 tokens/s、请求吞吐、批处理大小 系统每秒处理的请求数或生成的 token 数,反映整体产能
延迟 ms, s TTFT、TPOT、端到端延迟、P99/P95 用户可感知的等待时间,尤其首 token 延迟影响交互体验
GPU 利用率 % SM 利用率、显存占用、显存带宽 算力与显存是否被高效使用,是否存在瓶颈或浪费

其中,TTFT(Time To First Token) 衡量从请求发出到收到第一个 token 的时间,直接影响流式输出的“首字延迟感”;TPOT(Time Per Output Token) 衡量每个输出 token 的生成耗时,决定生成速度的平滑度。vLLM 的 continuous batching 机制使得这两个指标与并发数、KV Cache 命中率、显存碎片化程度高度相关。

实践建议:生产环境至少同时记录 TTFT 的 P50/P95/P99 和 TPOT 的 P50/P95。仅看平均值会掩盖长尾请求——当某个请求因 KV Cache 换出或 preemption 被抢占时,其 TPOT 可能飙升 5~10 倍,而平均值变化不大。

监控工具链与日志分析

vLLM 原生提供 Prometheus 格式的指标端点,同时可通过 Python logging 输出结构化日志。推荐组合使用以下工具:

  • Prometheus + Grafana:采集 vLLM 的 /metrics 端点,绘制吞吐、延迟、GPU 指标的时间序列曲线。
  • DCGM Exporter:采集 GPU 硬件级指标(SM 占用率、显存温度、功耗、PCIe 带宽),弥补 vLLM 自身指标在硬件层的空白。
  • 结构化日志:启用 --log-requests 参数,将每个请求的延迟、token 数、是否被抢占等信息输出为 JSON 行,便于后续关联分析。
# 启动 vLLM 时启用 Prometheus 指标与请求日志
python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Llama-3.1-8B-Instruct \
    --gpu-memory-utilization 0.90 \
    --max-num-seqs 256 \
    --enable-prompt-tokens-details \
    --log-requests \
    --port 8000

# 验证指标端点
curl -s http://localhost:8000/metrics | grep vllm:num_requests_running

vLLM 暴露的核心指标包括:vllm:num_requests_running(当前正在处理的请求数)、vllm:num_requests_waiting(排队请求数)、vllm:gpu_cache_usage_perc(KV Cache 使用率)、vllm:time_to_first_token_seconds 直方图、vllm:time_per_output_token_seconds 直方图。这些指标配合 DCGM 的 sm_utilization 和 framebuffer_usage,可以构建完整的性能视图。

指标关联分析:从数据定位瓶颈

单看某个指标很难定位问题。例如 GPU 利用率低,可能是请求量不足,也可能是显存碎片导致 batch 无法扩大。因此需要建立指标间的关联分析路径。下图展示了从原始指标到瓶颈定位的判断逻辑:

指标采集层 vLLM /metrics + DCGM 日志层 请求级 JSON 日志 存储与可视化 Prometheus + Grafana 关联分析:吞吐 vs 延迟 vs GPU 利用率 判断是否存在瓶颈或资源浪费 GPU 利用率低 检查:请求并发数是否不足? max-num-seqs 是否过小? 是否存在 CPU 预处理瓶颈? 延迟升高 TTFT 高 → 排队或调度延迟 TPOT 高 → 显存瓶颈或抢占 检查 KV Cache 命中率 吞吐量低 输出 tokens/s 低于预期 检查 batch 大小是否被限制 是否存在显存碎片化 综合判断路径 ① 先看 GPU SM 利用率 → ② 再看 KV Cache 使用率 ③ 结合 TTFT/TPOT 直方图 → ④ 最后查请求日志确认抢占与排队

实际排障时,建议按以下顺序检查:

  1. 确认 GPU SM 利用率与显存利用率是否匹配。若 SM 利用率高但显存利用率低,说明算力吃紧但 KV Cache 未充分利用,可尝试增大 --max-num-seqs 或调整调度策略。
  2. 观察 KV Cache 使用率(gpu_cache_usage_perc)。若持续接近 100%,说明显存容量成为硬约束,需考虑降低 --gpu-memory-utilization 预留余量,或升级更大显存 GPU。
  3. 分析 TTFT 直方图。若 P95 远高于 P50,说明存在排队效应,应关注 num_requests_waiting 指标,必要时增加实例或启用请求优先级。
  4. 分析 TPOT 直方图。若 TPOT 出现周期性尖峰,结合日志中的 preemption 字段,判断是否因显存不足导致请求被抢占重启。

案例:一次吞吐量骤降的定位过程

某团队运行 Llama-3.1-70B 服务,某次发布后吞吐量从 1200 tokens/s 骤降至 800 tokens/s,但 GPU SM 利用率反而从 85% 升至 92%。初步看“GPU 更忙了”,似乎不像是资源不足。通过 Grafana 查看指标后发现:

  • vllm:num_requests_running 从 64 降至 32,说明并发度下降了一半。
  • vllm:gpu_cache_usage_perc 从 85% 升至 98%,接近上限。
  • 请求日志中大量出现 "preemption": "swap" 记录。

进一步检查代码变更,发现新版本将 --max-model-len 从 4096 增加到 8192,导致每个请求占用的 KV Cache 空间翻倍,显存能容纳的并发请求数减半。虽然 SM 利用率因 batch 内 token 密度增加而上升,但整体吞吐反而下降。回滚配置后吞吐恢复。

关键教训:GPU 利用率高并不等于吞吐高。当显存容量受限时,过大的 max-model-len 或过高的 gpu-memory-utilization 会导致频繁的 preemption,GPU 花大量时间在 swap 而非计算上。监控时必须同时观察 SM 利用率和 KV Cache 使用率,二者背离往往是显存瓶颈的信号。

常见误区与复盘清单

在监控体系搭建过程中,以下误区最容易导致误判:

  • 只盯 GPU 利用率,忽略排队延迟。GPU 100% 时可能已有大量请求在等待,此时用户体验已严重劣化。
  • 用平均值掩盖长尾。TPOT 平均值 50ms 但 P99 达到 500ms,说明存在严重的抢占或显存抖动,必须查看直方图。
  • 忽略 CPU 与 GPU 间的数据传输。当 batch 较小时,CPU 预处理(tokenization、prompt 处理)可能成为瓶颈,此时 GPU 利用率低但吞吐也低。
  • 日志采样率不足。生产环境若只记录 1% 的请求日志,将无法捕捉偶发的 preemption 事件。

建议每两周进行一次监控体系复盘,检查以下清单:

  1. 是否所有核心指标(吞吐、TTFT、TPOT、SM 利用率、KV Cache 使用率)都有 7×24 小时历史曲线?
  2. 是否设置了合理的告警阈值?例如 KV Cache 使用率超过 95% 持续 5 分钟即告警。
  3. 请求日志是否包含 preemption、prompt tokens、output tokens、调度延迟等关键字段?
  4. 是否能在 5 分钟内定位吞吐下降是源于外部流量变化、配置变更还是代码发布?

通过建立指标关联分析的习惯,将监控数据与业务场景结合,才能在高并发下真正保障 vLLM 的吞吐稳定性,而不是被动响应告警。