部署形态与可观测性
本章回答:前十章的组件在生产中以什么进程拓扑组装,健康与性能如何观测,故障会在哪里暴露。
常见部署拓扑
把前面的组件组装起来,得到三种典型部署形态:
flowchart TB
subgraph S1["单机单卡(最简)"]
A1["API 进程<br/>AsyncLLM + InprocClient/MPClient"] --> E1["EngineCore 进程"]
E1 --> W1["Worker(UniProcExecutor)<br/>GPU 0"]
end
subgraph S2["单机多卡(TP)"]
A2["API 进程"] --> E2["EngineCore 进程"]
E2 --> M["MultiprocExecutor"]
M --> W2["Worker × N<br/>GPU 0..N-1"]
end
subgraph S3["多机(TP + PP / DP)"]
A3["API 进程 ×1"] --> E3["EngineCore 进程"]
E3 --> R["RayDistributedExecutor"]
R --> W3["Worker(跨节点 Ray actor)"]
end三条部署轴相互正交,可以按需叠加:
- API 进程数:
--api-server-count支持多个 API 进程共享一组 EngineCore(entrypoints/cli/serve.py:68附近的参数处理),协议处理与渲染是纯 CPU 工作,可以独立扩容; - DP:
--data-parallel-size起 N 套 EngineCore,各带自己的调度与模型副本;API 侧按各 rank 的排队长度做负载均衡(第 5 章提到的publish_dp_lb_stats,vllm/v1/engine/core.py:1483); - 执行器后端:单机默认 MultiprocExecutor,跨机用 Ray(
vllm/v1/executor/abstract.py:64)。
生命周期控制
部署态需要的启停原语都挂在 EngineClient 上,由 EngineCore 逐级转发到 Worker:
- 睡眠与唤醒:
AsyncLLM.sleep()(vllm/v1/engine/async_llm.py:1096)/wake_up()——让引擎释放显存给其他进程(如权重更新后的重新加载),level参数区分释放 KV 还是连同模型权重; - profile 开关:
start_profile/stop_profile(:1067)包装 torch profiler; - 准停:
pause_generation/resume_generation(:914),对应调度器的PauseState; - 健康检查:
check_health()(:1062)——AsyncLLM 侧仅检查内部错误标志,真正的存活由 ZMQ 通道的活性保证。
指标体系
可观测性三件套各归其位:
- Prometheus 指标:
vllm/v1/metrics/loggers.py定义StatLoggerBase(:49),output_handler每步调用record()(async_llm.py的 output 循环末尾)喂入迭代统计(TTFT、每步 token 数、缓存命中)与调度统计(队列长度、KV 使用率,SchedulerStats由run_busy_loop的_maybe_publish_request_counts主动推送,core.py:1483)。指标注册在v1/metrics/prometheus.py,桶配置在buckets.py; - KV 事件流:调度器周期性从
KVCacheManager.take_events()(vllm/v1/core/kv_cache_manager.py:716)取块存储/移除事件,经EventPublisherFactory(vllm/v1/core/sched/scheduler.py:20的导入)对外发布——供外部缓存网关感知哪些前缀已缓存; - 结构化日志:
log_stats系列方法输出吞吐统计行,供日志管道采集。
指标插件化:load_stat_logger_plugin_factories()(v1/metrics/loggers.py:79)允许插件注入自定义 stat logger,与第 13 章的 plugin 机制同源。
故障会在哪里暴露
结合进程模型,故障有明确的暴露面:
- Worker 崩溃(CUDA OOM、非法访存):
MultiprocExecutor的 RPC 超时(VLLM_EXECUTE_MODEL_TIMEOUT_SECONDS,multiproc_executor.py:348)触发,EngineCore 报错退出,API 进程经 ZMQ 感知EngineCoreProc死亡并返回 5xx——进程隔离保证了 API 不会僵死; - EngineCore 崩溃:
BackgroundResources.validate_alive()(core_client.py:543)在读消息时校验 ZMQ 帧,死连接转化为AsyncLLM.errored状态,健康检查随之失败; - 抢占风暴:KV 使用率长期顶着 watermark、频繁 recompute——这是调度层症状,只能靠 Prometheus 的 KV usage 与抢占计数发现,需要扩容或调
gpu_memory_utilization。
值得注意的是 vLLM 不做引擎内的请求持久化:进程崩溃即丢失全部在途请求,重试语义留给客户端——这是"调度器状态全部在内存"设计的直接代价。
本章收束
- 部署 = API 进程数 × DP 规模 × 执行器后端三个正交选择,组件不因形态改变职责;
- 观测三件套:Prometheus(每步统计)、KV 事件流(外部网关)、结构化日志;指标与事件都从调度器/输出处理器单点流出;
- 故障暴露面与进程边界一致:Worker 死于执行超时、EngineCore 死于调度异常、API 进程只优雅降级。
至此正文章节结束。附录提供按读者目标组织的阅读路径、核心符号速查与术语表。