内容提要
本文介绍如何用 vLLM、NixlConnector 和 toy Proxy 搭建单容器 PD 分离 Demo:Proxy 将请求改写为 max_tokens=1 发给 Prefill,Prefill 计算 Prompt 并生成 KV Cache,返回临时 Token 和传输元数据;Proxy 丢弃 Token,携带 kv_transfer_params 转发给 Decode;Decode 通过 NIXL 从 Prefill 拉取 KV Cache 并继续生成,结果经 Proxy 返回客户端。日志中 Num successful transfers=1 可确认传输成功。
延伸解读
控制流与数据流分离:Proxy 与 NIXL 各司其职
文章明确区分了两条链路:控制请求通过 Proxy 的 HTTP 端口在 Prefill 和 Decode 之间转发,而 KV Cache 数据不经过 Proxy,由 Decode 根据元数据通过 NIXL 直接从 Prefill 拉取。这意味着 Proxy 只负责请求编排和参数改写,Connector/NIXL 负责实际的数据传输。理解这一分工,有助于排查问题时快速定位是编排层还是传输层出现异常。
单容器 Demo 的边界:简化环境不等于合并实例
Demo 将 Prefill、Decode 和 Proxy 放在同一个容器、同一张 GPU 上,HTTP 地址和 NIXL 地址都表现为回环地址。但文章强调,Prefill 和 Decode 仍是两个独立的 vLLM 实例,分别监听不同端口,拥有各自的 KV Cache 管理和 NIXL Connector。这种简化降低了环境准备和网络配置的复杂度,适合观察请求与 KV Cache 流向,但不能据此推断生产环境中的网络与调度行为。
验证传输成功:不能只看 HTTP 200
文章指出,HTTP 200 只能证明接口返回成功,还需要结合 Decode 日志确认 KV Cache 传输。关键证据是 Decode 日志中的 Num successful transfers=1,它表示 Decode 侧至少完成了一次 NIXL KV Cache 传输。NIXL compatibility check passed 仅说明两端配置兼容,不能单独证明本次请求已完成传输。因此,验证 PD 分离是否真正生效,应同时检查传输计数和请求日志。
从 Demo 到生产:关注点会从“能否传输”转向“如何管理”
文章提醒,Demo 只有一个 Prefill、一个 Decode,且同容器同 GPU,而生产环境面临更多挑战:KV Cache 的生命周期、释放回收、超时重试与跨节点带宽;多实例下的 P/D 调度与容量配比;Prefill 成功但 Decode 失败等故障处理;以及性能与可观测性。PD 分离主要解决 Prefill 和 Decode 相互干扰的问题,让 TTFT 和 ITL 可分别优化,但代价是多了一层调度和传输,需要判断收益是否大于成本。
Q&A
vLLM PD 分离中,Prefill 和 Decode 分别负责什么?
Prefill 负责计算完整 Prompt 并生成 KV Cache,同时返回一个临时 Token 和 KV Transfer 元数据;Decode 负责根据元数据通过 NIXL 拉取 KV Cache,并基于已有上下文继续逐 Token 生成最终结果。
PD 分离 Demo 中,Proxy 是如何改写请求并转发给 Prefill 和 Decode 的?
Proxy 先将客户端请求改写为 max_tokens=1 发送给 Prefill;Prefill 返回临时 Token 和 KV Transfer 元数据后,Proxy 丢弃临时 Token,取出 kv_transfer_params 覆盖到原始请求上,并恢复客户端要求的 max_tokens,再发送给 Decode。
KV Cache 在 PD 分离中是如何从 Prefill 传输到 Decode 的?
KV Cache 不经过 Proxy,而是由 Decode 根据 Prefill 返回的元数据(如 remote_engine_id、remote_request_id、remote_block_ids、NIXL side channel 地址和端口等),通过 NIXL 直接从 Prefill 拉取。
如何确认 PD 分离中 KV Cache 传输成功?
可以查看 Decode 日志,出现“KV Transfer metrics: Num successful transfers=1”即表示 Decode 侧至少完成了一次 NIXL KV Cache 传输;同时 Prefill、Decode 和 Proxy 的请求日志都应返回 200 OK。
为什么最终返回给客户端的响应中 kv_transfer_params 为 null?
因为 kv_transfer_params 是 KV Transfer 元数据,只在 Proxy 内部从 Prefill 传给 Decode,用于定位和拉取 KV Cache;最终响应是 Decode 生成并返回给客户端的,所以其中的 kv_transfer_params 为 null 是正常的。
PD 分离在生产环境中面临哪些主要挑战?
主要挑战包括:KV Cache 管理(生命周期、释放回收、超时重试、跨节点带宽开销)、P/D 实例调度(根据负载和缓存命中选择实例)、P/D 容量配比与扩缩容、故障处理(重试、状态清理、缓存回收),以及性能与可观测性(关注排队时间、传输耗时、带宽和失败情况,判断拆分收益是否大于成本)。