- 人工智能
- 大模型
- 模型推理服务
- 后端
【免费下载链接】Mooncake
Mooncake is the serving platform for Kimi, a leading LLM service provided by Moonshot AI.
本文是 Mooncake 仓库中 vLLM V0 Disaggregated Serving with MooncakeStore 文档的深度展开版本。它以 vLLM 官方仓库的 PR #10502(intra-node KVCache 传输)与 PR #12957(inter-node 场景支持)为基础,介绍如何利用 MooncakeStore 作为共享 KV 缓存池,将 vLLM 的 Prefill(预填充)与 Decode(解码)实例解耦为独立的集群角色,并通过 RDMA/TCP 在实例之间高速搬运 KV Cache。读完本文,你将掌握:
mooncake-transfer-engine与 vLLM V0 的安装组合、mooncake.json配置文件的完整字段语义、多实例kv_producer/kv_consumer集群的启动方式,以及带动态扩缩容能力的 XpYd 代理服务器(disagg_proxy_demo.py)的部署与验证流程。
:class: warning 本文对应的 vLLM V0 集成方案在当前仓库中已被标记为 **Archived**,其内容已合并进统一的 [KV Cache Storage & Sharing 指南](https://link.gitcode.com/i/d161905b1fdfe82b7957af39960ea09d)(见其中的 V0 Legacy 章节)。该方案仍处于实验阶段,接口细节可能随 vLLM 社区反馈而调整;新部署建议优先参考 [vLLM V1 LMCache integration](https://link.gitcode.com/i/139727f175c77c45a1e14a6121c50455) 对应的 V1 集成方案。一、背景:为什么需要分离式 Prefill-Decode 服务
在传统的单体 vLLM 部署中,一次请求的 Prefill(一次性处理整个 prompt、产生 KV Cache)与 Decode(逐 token 自回归生成、逐步消费 KV Cache)在同一实例上串行完成。这种模式存在两个结构性瓶颈:
- 显存中的 KV Cache 容量被单机限制:长上下文请求会迅速占满 GPU 显存中的 KV 缓存,吞吐受限于单实例的缓存池大小;
- 两种阶段的最优资源配比不同:Prefill 是计算密集型(attention 矩阵计算量大),Decode 是访存/带宽密集型(每次仅新增一个 token 的 KV)。把两类负载混跑,很难同时调优。
Mooncake 提供的 vLLM V0 集成方案将二者拆开:**Prefill 实例(kv_producer)**只负责把 prompt 计算成 KV Cache,随后通过 Mooncake 的传输引擎(底层协议支持 RDMA/TCP)将 KV 块搬运到Decode 实例(kv_consumer),后者直接以收到的 KV Cache 为起点继续生成,不再重复计算 prompt。这就是业内常说的 Disaggregated Prefill-Decode(PD 分离式服务,本仓库文档中也称为XpYd,其中 X 表示 Prefill 实例数量、Y 表示 Decode 实例数量)。
与旧版 v0.x 集成相比,本版(v0.3 起的架构)引入了两个关键变化(原文 "Main changes from v0.x to v1"):
- XpYd 支持与编排:可以在运行时动态调整 Prefill 组与 Decode 组的实例数量,而无需重启整个集群;
- 更强的稳定性与容错:单个 vLLM 实例的意外崩溃是可容忍的;由于实例之间不再存在相互直连的连接(KV 的搬运改由 Mooncake 的 master/元数据服务编排),每个实例本质上仍是一个原生 vLLM 实例,即使请求不经过代理直接打到某个实例,也能被正常服务完毕。
二、安装与版本兼容性
2.1 安装 mooncake-transfer-engine
先安装传输引擎的 Python 包:
pip3 install mooncake-transfer-engine安装注意点(原文明确提示):
如果运行时报错缺少
lib*.so动态库,需要先卸载该 pip 包,再按 构建指南 手动编译二进制产物:pip3 uninstall mooncake-transfer-engine版本匹配约束:若使用的 vLLM 版本 ≤ v0.8.4,则要求
mooncake-transfer-engine <= 0.3.3.post2。此外,在最新版传输引擎中,旧的mooncake_vllm_adaptor接口已被废弃(deprecated),不再使用。
2.2 安装最新版 vLLM(V0 后端)
由于 PD 分离特性当前只在 vLLM V0 引擎上支持,需要从源码安装:
# 1. 克隆 vLLM 官方仓库 git clone git@github.com:vllm-project/vllm.git # 2. 进入目录并从源码构建(包含 C++ 与 CUDA 代码) cd vllm pip3 install -e .- 如果构建失败,可先尝试升级 cmake:
pip3 install cmake --upgrade(这一提示来自仓库中同主题的 disagg-prefill-decode 指南); - 若遇到无法自行解决的问题,请参考 vLLM 官方的安装/编译指南。
从仓库的基准测试脚本可以印证该组合的典型用法:benchmarks/xypd_benchmarks/vllm-benchmarks/benchmarks.sh 中同样显式设置了export VLLM_USE_V1=0,并通过pip install vllm准备运行环境,随后以python3 -m vllm.entrypoints.openai.api_server拉起实例。
三、配置文件 mooncake.json 详解
Prefill 与 Decode 实例需要各自准备一份mooncake.json。同一节点上的所有 Prefill/Decode 实例可以共享同一份配置文件。
3.1 RDMA 场景
{ "local_hostname": "192.168.0.137", "metadata_server": "etcd://192.168.0.137:2379", "protocol": "rdma", "device_name": "erdma_0", "master_server_address": "192.168.0.137:50001" }3.2 TCP 场景
{ "local_hostname": "192.168.0.137", "metadata_server": "etcd://192.168.0.137:2379", "protocol": "tcp", "device_name": "", "master_server_address": "192.168.0.137:50001" }3.3 字段语义与取值说明
| 字段 | 含义 | 取值说明 |
|---|---|---|
local_hostname | 当前节点用于与元数据服务器通信的 IP 地址 | 取值为本机可被其他节点访问到的地址,如"192.168.0.137" |
metadata_server | Mooncake 传输引擎的元数据服务器地址 | 支持三种后端,见下方示例;也支持逗号分隔的多副本地址 |
protocol | 数据传输协议 | "rdma"或"tcp" |
device_name | 数据传输使用的设备 | 仅当protocol为"rdma"时必填;多 NIC 时用逗号分隔且不能有空格,如"erdma_0,erdma_1";TCP 场景填"" |
master_server_address | MooncakeStore master 守护进程的 IP 与端口 | 形如"192.168.0.137:50001",须与下方启动的mooncake_master --port 50001对应 |
metadata_server三种后端写法(来自原文及仓库中同系列文档):
- etcd 后端:
"192.168.0.137:2379"、"etcd://192.168.0.137:2379"或带副本的"etcd://192.168.0.137:2379,192.168.0.138:2379"; - redis 后端:
"redis://192.168.0.137:6379"; - http 后端:
"http://192.168.0.137:8080/metadata"。
从仓库后续演进可以进一步理解这些字段的背景:在更早的 v0.2 版集成(对应 vllm-integration-v0.2.md)中,配置文件还需要prefill_url/decode_url/metadata_backend等字段来显式描述两端地址;而 v0.3 版改用local_hostname+ 元数据服务器 +master_server_address的方式,实例之间不再需要感知彼此 URL,这正是原文所述"instance-to-instance connections are removed"的落地体现——节点通过 MooncakeStore 的统一元数据完成 KV 块寻址与搬运。
四、端到端运行示例
以下命令均假定你在 vLLM 仓库克隆目录的根目录下执行,并且所有 IP、端口请按实际环境替换。原文档特别提醒:如果某些 vLLM 实例异常退出,连接元数据可能因未正常清理而损坏,此时建议重启
mooncake_master后再进行下一轮测试。
第 1 步:启动 etcd
etcd --listen-client-urls http://0.0.0.0:2379 --advertise-client-urls http://localhost:2379 # 运行前可能需要先终止其他占用 2379 端口的 etcd 进程第 2 步:启动 mooncake_master
mooncake_master --port 50001mooncake_master即 MooncakeStore 的 master 守护进程,其可执行目标由仓库源码构建产生(见 mooncake-store/src/CMakeLists.txt 中add_executable(mooncake_master master.cpp),并安装到bin目录)。它负责维护各实例的连接元数据,使 KV 块可以在 Prefill 与 Decode 实例间正确寻址、搬运。
第 3 步:启动多个 vLLM 实例
kv_producer(Prefill)角色——4 个实例,分别绑定 GPU 0~3、端口 8100~8103:
MOONCAKE_CONFIG_PATH=./mooncake.json VLLM_USE_V1=0 python3 -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-7B-Instruct-GPTQ-Int4 \ --port 8100 \ --max-model-len 10000 \ --gpu-memory-utilization 0.8 \ --kv-transfer-config '{"kv_connector":"MooncakeStoreConnector","kv_role":"kv_producer"}' CUDA_VISIBLE_DEVICES=1 MOONCAKE_CONFIG_PATH=./mooncake.json VLLM_USE_V1=0 python3 -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-7B-Instruct-GPTQ-Int4 \ --port 8101 \ --max-model-len 10000 \ --gpu-memory-utilization 0.8 \ --kv-transfer-config '{"kv_connector":"MooncakeStoreConnector","kv_role":"kv_producer"}' CUDA_VISIBLE_DEVICES=2 MOONCAKE_CONFIG_PATH=./mooncake.json VLLM_USE_V1=0 python3 -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-7B-Instruct-GPTQ-Int4 \ --port 8102 \ --max-model-len 10000 \ --gpu-memory-utilization 0.8 \ --kv-transfer-config '{"kv_connector":"MooncakeStoreConnector","kv_role":"kv_producer"}' CUDA_VISIBLE_DEVICES=3 MOONCAKE_CONFIG_PATH=./mooncake.json VLLM_USE_V1=0 python3 -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-7B-Instruct-GPTQ-Int4 \ --port 8103 \ --max-model-len 10000 \ --gpu-memory-utilization 0.8 \ --kv-transfer-config '{"kv_connector":"MooncakeStoreConnector","kv_role":"kv_producer"}'kv_consumer(Decode)角色——4 个实例,分别绑定 GPU 4~7、端口 8200~8203:
CUDA_VISIBLE_DEVICES=4 MOONCAKE_CONFIG_PATH=./mooncake.json VLLM_USE_V1=0 python3 -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-7B-Instruct-GPTQ-Int4 \ --port 8200 \ --max-model-len 10000 \ --gpu-memory-utilization 0.8 \ --kv-transfer-config '{"kv_connector":"MooncakeStoreConnector","kv_role":"kv_consumer"}' CUDA_VISIBLE_DEVICES=5 MOONCAKE_CONFIG_PATH=./mooncake.json VLLM_USE_V1=0 python3 -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-7B-Instruct-GPTQ-Int4 \ --port 8201 \ --max-model-len 10000 \ --gpu-memory-utilization 0.8 \ --kv-transfer-config '{"kv_connector":"MooncakeStoreConnector","kv_role":"kv_consumer"}' CUDA_VISIBLE_DEVICES=6 MOONCAKE_CONFIG_PATH=./mooncake.json VLLM_USE_V1=0 python3 -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-7B-Instruct-GPTQ-Int4 \ --port 8202 \ --max-model-len 10000 \ --gpu-memory-utilization 0.8 \ --kv-transfer-config '{"kv_connector":"MooncakeStoreConnector","kv_role":"kv_consumer"}' CUDA_VISIBLE_DEVICES=7 MOONCAKE_CONFIG_PATH=./mooncake.json VLLM_USE_V1=0 python3 -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-7B-Instruct-GPTQ-Int4 \ --port 8203 \ --max-model-len 10000 \ --gpu-memory-utilization 0.8 \ --kv-transfer-config '{"kv_connector":"MooncakeStoreConnector","kv_role":"kv_consumer"}'第 3.1 步:命令行参数逐项说明
| 参数/环境变量 | 作用与约束 |
|---|---|
MOONCAKE_CONFIG_PATH | mooncake.json配置文件的路径 |
VLLM_USE_V1=0 | 必须设置:PD 分离特性当前仅在 vLLM V0 引擎上支持。也可以export VLLM_USE_V1=0到环境变量,避免在每个命令前重复书写 |
VLLM_USE_MODELSCOPE | 可选;如果能直接访问 HuggingFace,请去掉该变量 |
--model | 指定模型(示例为Qwen/Qwen2.5-7B-Instruct-GPTQ-Int4) |
--port | vLLM 服务监听端口 |
--max-model-len | 模型支持的最大序列长度(示例为 10000) |
--gpu-memory-utilization | GPU 显存利用率(示例为 0.8) |
--tensor_parallel_size/-tp | 支持张量并行,例如追加-tp 2使用多 GPU 运行;所有实例的tensor_parallel_size必须一致。若 Prefill 与 Decode 同机运行,请用不同的CUDA_VISIBLE_DEVICES区分,例如 Prefill 用CUDA_VISIBLE_DEVICES=0,1、Decode 用CUDA_VISIBLE_DEVICES=2,3 |
--kv-transfer-config | JSON 字符串,指定 KV 传输连接器及其配置;kv_connector固定为"MooncakeStoreConnector",kv_role取"kv_producer"、"kv_consumer"或"kv_both"之一 |
关于kv_role的补充:kv_producer是产出 KV Cache 的 Prefill 节点,kv_consumer是消费 KV Cache 的 Decode 节点,kv_both则同时具备两者能力(在 MooncakeStoreConnector 指南 中,kv_both被用于单节点 KV Cache 卸载场景)。MooncakeStoreConnector与旧版MooncakeConnector的关键差异在于:前者将 KV 块写入MooncakeDistributedStore这一共享 KV 缓存池(支持 CPU/SSD 卸载、基于块哈希的跨实例前缀缓存复用),而后者是实例间的直连传输。
仓库基准脚本 benchmarks/xypd_benchmarks/vllm-benchmarks/benchmarks.sh 的launch_nodes()函数(见第 89~126 行)正是以上述方式批量拉起 Prefill/Decode 实例,并通过wait_for_server轮询/v1/models等待实例就绪,可作为批量编排的参考实现。
第 4 步:启动代理服务器
cd vllm python3 examples/online_serving/disagg_examples/disagg_proxy_demo.py \ --model Qwen/Qwen2.5-7B-Instruct-GPTQ-Int4 \ --prefill localhost:8100 localhost:8101 \ --decode localhost:8200 localhost:8201 \ --port 8000参数说明:
--model:指定模型名,同时作为代理的 tokenizer;--port:代理服务监听端口(默认 8000);--prefill/-p:vLLM Prefill 实例的 IP:端口列表;--decode/-d:vLLM Decode 实例的 IP:端口列表。
该代理的工作模式(从仓库源码 benchmarks/xypd_benchmarks/proxy_demo.py 可以完整印证):
- 收到
/v1/completions或/v1/chat/completions请求后,将请求副本的max_tokens改为 1,按调度策略(默认RoundRobinSchedulingPolicy,见 proxy_demo.py)转发给某个 Prefill 实例,只做 Prefill、产出 KV Cache(见create_completion中 "Perform kv recv and decoding stage" 之前的逻辑,proxy_demo.py); - 随后将原始请求转发给某个 Decode 实例,后者通过 MooncakeStoreConnector 取回 KV Cache,直接开始 Decode,最终以流式响应返回给客户端。
需要注意的是:这个disagg_proxy只是 Mooncake 团队基于 round-robin 策略实现的演示性代理。在生产阶段,服务提供商可以按自身需求实现对应的全局代理调度策略(如按负载、按前缀命中率等)。此外,代理在转发失败时还会自动将故障实例从列表中移除(remove_instance_endpoint),体现了"单个实例崩溃可容忍"的设计目标。
第 4.1 步:运行时动态调整 Prefill/Decode 实例(XpYd 编排)
如果需要在不重启的情况下动态增减 p-node 与 d-node,需要先配置管理员 API Key:
export ADMIN_API_KEY="xxxxxxxx" # 或直接在启动命令前注入: ADMIN_API_KEY="xxxxxxxx" python3 vllm/examples/online_serving/disagg_examples/disagg_demo.py \ --model Qwen/Qwen2.5-7B-Instruct-GPTQ-Int4 \ --prefill localhost:8100 localhost:8101 \ --decode localhost:8200 localhost:8201 \ --port 8000 \ --scheduling round_robin然后通过管理接口把新实例加入 Prefill 组或 Decode 组:
curl -X POST "http://localhost:8000/instances/add" -H "Content-Type: application/json" -H "X-API-Key: $ADMIN_API_KEY" -d '{"type": "prefill", "instance": "localhost:8102"}' curl -X POST "http://localhost:8000/instances/add" -H "Content-Type: application/json" -H "X-API-Key: $ADMIN_API_KEY" -d '{"type": "prefill", "instance": "localhost:8103"}' curl -X POST "http://localhost:8000/instances/add" -H "Content-Type: application/json" -H "X-API-Key: $ADMIN_API_KEY" -d '{"type": "decode", "instance": "localhost:8202"}' curl -X POST "http://localhost:8000/instances/add" -H "Content-Type: application/json" -H "X-API-Key: $ADMIN_API_KEY" -d '{"type": "decode", "instance": "localhost:8203"}'查询代理当前状态:
curl localhost:8000/status | jq从实现上看,/instances/add接口受ADMIN_API_KEY校验保护(见 proxy_demo.py 的api_key_authenticate),新增实例前会先请求该实例的/v1/models校验模型是否一致(validate_instance),校验通过后才会加入对应列表并重建 round-robin 迭代器;/status返回prefill_node_count、decode_node_count及两组节点列表。这正是 XpYd 动态编排能力的直接证据。
再次强调:请务必将命令中的 IP 地址替换为你自己的环境地址。
五、用 OpenAI 兼容接口验证
向代理发送一个 completions 请求:
curl -s http://localhost:8000/v1/completions -H "Content-Type: application/json" -d '{ "model": "Qwen/Qwen2.5-7B-Instruct-GPTQ-Int4", "prompt": "San Francisco is a", "max_tokens": 1000 }'- 如果请求不是从代理所在机器发出,请把
localhost改为代理服务器的 IP 地址; - 仓库的端到端测试 scripts/e2e/scripts/test_vllm_1p1d_erdma.sh 提供了同类验证模板:它在一台机器上启动
kv_consumer(端口 8020)、另一台机器启动kv_producer(端口 8010),再通过curl /v1/chat/completions发送请求并校验响应内容,可作为集成测试的参考。
六、架构要点与使用限制
- KV 搬运路径:Prefill 实例产生的 KV 块通过 Mooncake 传输引擎(
protocol: rdma/tcp)进入共享 KV 缓存池,Decode 实例按需取回。master_server_address指向的mooncake_master是这一过程的核心协调者,因此当实例异常退出导致元数据损坏时,重启mooncake_master是最直接的处理手段。 - 角色划分:同一份
mooncake.json可被同节点的多个实例共享;角色完全由--kv-transfer-config中的kv_role决定,与配置文件无关。 - 容错与独立性:由于实例间无直接连接,每个实例仍是原生 vLLM 实例,可独立完成不经过代理的请求,单实例崩溃不会拖垮集群。
- 实验性声明:原文档明确标注该集成仍为实验版本,会依据 vLLM 社区反馈随时调整;且 PD 特性仅在 V0 引擎可用(
VLLM_USE_V1=0)。对于新部署,请优先转向仓库提供的 vLLM V1 方案(见 vLLM V1 LMCache integration 与 vLLM V1 Mooncake Store 性能文档)。
七、延伸阅读
- 统一的 KV Cache Storage & Sharing 指南:当前仓库推荐使用的整合版指南,包含 V0 Legacy 与 V1 两个章节;
- MooncakeStoreConnector 部署指南:讲解
MooncakeDistributedStore共享 KV 池、CPU/SSD 卸载、kv_both单节点场景与MultiConnector组合用法(含PYTHONHASHSEED=0保证 DP 各 rank 块哈希一致的注意事项); - Disaggregated Prefill-Decode 指南:统一了 V1(推荐)与 V0(遗留)两套
MooncakeConnector使用方式,并提供故障排查建议; - 基准测试脚本 benchmarks/xypd_benchmarks/vllm-benchmarks/benchmarks.sh 与代理实现 benchmarks/xypd_benchmarks/proxy_demo.py:分别展示了 1P1D、2P1D、2P2D、2P4D、4P4D 等多组 XpYd 组合下的批量压测方法与可扩展的代理实现;
- 构建依赖与入门指引:构建指南、快速开始。
- 人工智能
- 大模型
- 模型推理服务
- 后端
【免费下载链接】Mooncake
Mooncake is the serving platform for Kimi, a leading LLM service provided by Moonshot AI.
相关推荐
Cap 开源录屏完整指南:录制、剪辑、分享链接 3 步跑通,还能自建私有服务器
Cap 开源录屏完整指南:录制、剪辑、分享链接 3 步跑通,还能自建私有服务器 要给产品录一段演示视频发给客户,或者把一个 bug 现场丢给开发同事,用传统流程
屏幕录制音视频桌面应用后端前端视频处理AI 应用移动开发AIBrix + AWS Neuron(Trainium2)P/D 分离式推理部署指南:基于 NIXL/EFA 的 Prefill/Decode 架构实战
AIBrix + AWS Neuron(Trainium2)P/D 分离式推理部署指南:基于 NIXL/EFA 的 Prefill/Decode 架构实战 导读
人工智能大模型云原生模型推理服务LLM 网关API网关弹性伸缩SGLang PD 分离模式下如何用 bench_serving 分别剖析 prefill 与 decode worker?
SGLang PD 分离模式下如何用 bench_serving 分别剖析 prefill 与 decode worker? 在 SGLang 的 PD(Pre
模型推理服务推理引擎人工智能大模型本地部署多模态
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考