3、性能诊断工具:使用vLLM内置指标、Prometheus、Grafana监控吞吐瓶颈

核心原理:从“黑盒压测”到“白盒观测”

吞吐优化不能靠猜测。许多团队在压测时只关注最终的总吞吐量(tokens/s),一旦数字不达标,便盲目调整--max-num-seqs或--gpu-memory-utilization,结果往往事倍功半。vLLM 的价值在于其PagedAttention 调度引擎和Continuous Batching机制,它们让 GPU 计算与 KV Cache 显存管理深度耦合。要定位瓶颈,必须回答三个问题:GPU 算力是否吃满?KV Cache 是否成为容量或带宽瓶颈?调度器是否在空转等待?

vLLM 内置的 Prometheus 指标端点(/metrics)将上述问题转化为可量化的时序数据。其核心原理是:vLLM 的 metrics 采集器在每个调度周期(iteration)结束时,记录引擎内部的计数器与直方图,包括:当前等待序列数、正在运行的序列数、KV Cache 使用量、GPU 缓存命中率、单次 decode 迭代耗时等。这些指标通过 HTTP 暴露,由 Prometheus 按固定间隔抓取,再交由 Grafana 进行可视化与告警。理解这一数据链路,是后续所有诊断动作的基础。

关键指标速查清单

指标名称类型含义与诊断价值
vllm:num_requests_runningGauge当前正在执行的序列数。若长期低于 max-num-seqs,说明并发不足或请求到达率低。
vllm:num_requests_waitingGauge排队中的序列数。持续大于 0 说明系统已过载,但需结合 GPU 利用率判断是算力瓶颈还是显存瓶颈。
vllm:gpu_cache_usage_percGaugeKV Cache 显存占用百分比。若长期 >90%,可能触发 preemption(抢占),导致请求被换出重算。
vllm:time_to_first_token_secondsHistogram首 token 延迟。若 P99 偏高,可能是 prefill 阶段计算密集或排队等待过长。
vllm:e2e_request_latency_secondsHistogram端到端请求延迟。结合吞吐量可判断系统是否处于“假忙”状态。
vllm:generation_tokens_totalCounter累计生成的 token 数,用于计算实际吞吐速率。

方法流程:三步建立监控看板

第一步:暴露 vLLM 指标端点。启动 vLLM 服务时,需显式指定 --metrics-port(默认 8000 端口与 API 共用)。若使用 OpenAI 兼容服务,可通过环境变量 VLLM_METRICS_PORT=8001 分离端口,避免请求量过大影响指标采集。验证方法:

curl -s http://localhost:8001/metrics | grep vllm:num_requests_running

第二步:配置 Prometheus 抓取任务。在 prometheus.yml 中添加 job,注意设置合理的 scrape_interval(建议 5s,过短会增加开销,过长会丢失瞬时峰值):

scrape_configs:
  - job_name: 'vllm'
    scrape_interval: 5s
    metrics_path: '/metrics'
    static_configs:
      - targets: ['10.0.0.12:8001']

第三步:在 Grafana 中构建诊断视图。推荐使用 vLLM Dashboard(ID: 19750)作为起点,但必须自定义两个核心面板:“吞吐与利用率联合视图”和“排队与抢占视图”。前者将 GPU 利用率(DCGM_FI_PROF_GR_ENGINE_ACTIVE)与 vllm:generation_tokens_total 的速率叠加,后者将 num_requests_waiting 与 gpu_cache_usage_perc 关联。

vLLM 吞吐瓶颈监控数据链路 vLLM Engine PagedAttention 调度 Continuous Batching (GPU 显存 / 算力) /metrics 端点 端口 :8001 Prometheus scrape_interval: 5s Grafana 看板 HTTP 抓取 时序存储 查询 Grafana 诊断面板核心视图 ① 吞吐与 GPU 利用率联合视图 tokens/s GPU % 时间 → ② 排队序列与 KV Cache 水位 10:00 10:05 10:10 10:15 10:20 90% 抢占阈值

上图展示了从 vLLM 引擎到 Grafana 看板的完整数据流。在实际诊断中,不要孤立地看单个指标。例如,当 num_requests_waiting 上升时,必须同时观察 GPU 利用率:若 GPU 利用率已接近 100%,则瓶颈在算力;若 GPU 利用率不足 60% 而 KV Cache 使用率超过 90%,则说明调度器因显存不足而无法将更多序列送入 GPU,此时应调整 --gpu-memory-utilization 或减少 --max-num-seqs。

案例:一次真实的生产瓶颈定位

某团队部署了 8 卡 A100(80GB)的 vLLM 服务,压测时发现吞吐量仅为预期的 60%。通过 Grafana 观察发现:vllm:gpu_cache_usage_perc 稳定在 95% 以上,而 GPU 计算利用率(DCGM)仅 45%。进一步查看 vllm:num_requests_running 始终徘徊在 32(配置的 max-num-seqs=64),且 vllm:num_preemptions_total 计数器在 10 分钟内增加了 200 余次。

根因分析:KV Cache 显存碎片化导致 PagedAttention 无法分配连续的物理块,即使总显存未满,调度器也无法容纳更多序列。解决措施:

  • 将 --max-num-seqs 从 64 降至 48,减少每个序列的显存预留。
  • 启用 --enable-prefix-caching,对共享前缀的请求复用 KV 块。
  • 调整 --block-size 为 32(默认 16),增大物理块粒度,减少碎片。

调整后,num_requests_running 稳定在 48,GPU 利用率升至 82%,吞吐量提升 45%。这一案例说明:监控的价值不在于“看数字”,而在于通过指标组合推断调度器内部状态。

误区与复盘:监控中的常见陷阱

误区一:只配置默认 Grafana 面板,不关注抢占指标。默认面板往往只展示延迟和吞吐,但 vllm:num_preemptions_total 才是反映显存压力的关键信号。建议在告警规则中加入:当 rate(vllm:num_preemptions_total[5m]) > 0.5 时触发警告。

误区二:将 Prometheus 抓取间隔设为 1s。vLLM 的指标更新周期与调度 iteration 相关(通常 10~50ms),但 1s 的抓取频率会显著增加 Python GIL 竞争,影响推理性能。实测 5s 间隔足以捕捉 95% 的波动。

误区三:忽略指标端口与 API 端口分离。若共用端口,高并发请求下 /metrics 响应可能超时,导致 Prometheus 抓取失败,形成数据空洞。

复盘要点:每次压测后,应导出 Prometheus 数据并对比 vllm:time_to_first_token_seconds 的 P95 与 vllm:generation_tokens_total 的速率曲线。若首 token 延迟升高而吞吐未降,说明 prefill 阶段成为瓶颈;若两者同步下降,则需检查网络或客户端连接池配置。监控不是终点,而是建立“指标→假设→实验→验证”闭环的起点。