Mooncake 仓库同时存在经典 Transfer Engine 和 TENT(Transfer Engine Next)。TENT 不是简单增加一种 Transport,而是重构了 Segment 生命周期、运行时调度、拓扑选择、QoS、故障转移和插件体系。
阅读版本:
Mooncake commit: 777cc7782417b6e554cf7c2d53210d0d8f89f5cc
一、为什么需要下一代引擎
经典 TE 已经支持 RDMA、TCP、NVLink 和多种硬件,但随着后端增加,TransferEngineImpl + MultiTransport + 各 Transport 容易出现几个问题:
- Segment 生命周期分散在元数据和后端注册逻辑中;
- 传输选择主要依赖静态协议与局部规则;
- 多 rail、拥塞、故障和 QoS 难以统一调度;
- 不同后端各自维护进度线程和资源模型;
- 新硬件接入需要理解大量经典内部约定;
- 请求取消、deadline 和 failover 缺少统一运行时。
TENT 将这些能力上移到 Runtime 层。
二、目录结构
TENT 核心位于:
tent/src/runtime/
├── transfer_engine_impl.cpp
├── segment.cpp
├── segment_manager.cpp
├── segment_registry.cpp
├── segment_tracker.cpp
├── transport_loader.cpp
├── transport_selector.cpp
├── progress_worker.cpp
├── admission_queue.cpp
├── qos_contract.cpp
├── receiver_credit.cpp
├── topology.cpp
├── control_plane.cpp
└── proxy_manager.cpp
外围包括:
metastore:etcd / redis / HTTP
rpc:控制面 RPC
platform:CPU/GPU 内存探测和分配
plugins:CUDA、ROCm 等平台插件
metrics:统一指标系统
transport:各传输插件
与经典 TE 相比,职责边界更加清晰。
三、兼容入口
公共 TransferEngine 仍然可以启用 TENT。src/transfer_engine.cpp 根据 use_tent_ 创建:
std::shared_ptr<mooncake::tent::TransferEngine>
经典参数会转换为 tent::Config:
local_server_name -> local_segment_name
metadata connection -> metadata_type + metadata_servers
这层兼容降低迁移成本,但 TENT 自己的原生 API 和配置能表达更多调度语义。
四、SegmentManager 集中管理生命周期
经典模式中,Segment 信息分布在 TransferMetadata、注册表和各 Transport。TENT 引入:
Segment
SegmentManager
SegmentRegistry
SegmentTracker
可以把它们理解为:
Segment:本地或远端地址空间对象;SegmentManager:创建、打开、注册和关闭 Segment;SegmentRegistry:维护可查找对象和注册关系;SegmentTracker:跟踪远端变化、引用和失效。
集中管理后,注销内存、远端重启、metadata 更新和正在执行的请求可以在同一生命周期模型中协调。
五、TransportLoader 与插件化
经典 MultiTransport::installTransport() 包含大量构建宏和 if (proto == ...) 分支。TENT 使用 TransportLoader 将后端加载与引擎核心解耦。
平台能力也通过 Device Plugin 扩展,例如 CUDA 和 ROCm 插件负责:
- 识别设备内存;
- 查询 device/NUMA 属性;
- 提供平台特有注册或拷贝能力;
- 向拓扑系统暴露设备关系。
这样新增硬件不必把所有条件编译逻辑堆进一个中心工厂。
六、TransportSelector
TENT 的 TransportSelector 不只按 Segment protocol 字符串路由,而是结合拓扑和运行期条件选择路径。
输入可以包括:
源、目标 memory type
源、目标节点和设备
拓扑距离
可用 transport
链路优先级
transport hint
当前 rail 状态
对应测试包括 topology priority matrix、transport hint、selector 等,说明选择逻辑被提升为可独立验证的模块。
理想决策可能是:
同 GPU / 同进程 -> 本地直接完成
同节点 GPU -> SHM / GPU IPC / NVLink
跨节点 GPU -> RDMA / EFA / UB
持久层 -> GDS / NVMe-oF
故障或不支持 -> TCP
七、ProgressWorker
TENT 用 ProgressWorker 统一推进异步操作。传统后端容易各自创建 poller,造成线程模型分散。
ProgressWorker 的职责类似事件循环:
取得待执行 operation
-> 提交后端请求
-> poll completion
-> 推进多阶段 operation
-> 处理 retry / cancel / timeout
-> 完成用户 future/callback
测试覆盖 poll backoff 和 progress worker,意味着实现会在低延迟与空闲 CPU 消耗之间做权衡,而不是无限 busy polling。
八、AdmissionQueue 与 QoS
经典 TE 主要回答“怎样传”,TENT 进一步回答“现在是否应该传、谁先传”。
AdmissionQueue 和 QoSContract 可以支持:
- 带宽上限;
- 请求优先级;
- deadline;
- 多租户公平性;
- 大请求切片;
- 拥塞时的 admission control;
- deadline promotion。
仓库测试包含 bandwidth arbitration、deadline promotion 和 QoS contract。这说明 TENT 面向的不只是 microbenchmark 峰值带宽,而是共享 AI 集群中的可预测服务质量。
九、Receiver Credit
发送方很快并不代表接收方能无限承受请求。TENT 引入 receiver credit 管理接收端资源:
接收端公布 credit
-> 发送端消费 credit 提交
-> 请求完成后归还
-> credit 不足则排队或限流
它可以避免接收端 staging buffer、队列或 RPC handler 被突发流量压垮。对需要双边协议或 remote stage 的后端尤其重要。
十、Remote Stage 与代理路径
并非所有源和目标都能直接建立单边访问。TENT 的 remote_stage_operation 和 proxy_manager 支持分阶段路径:
源设备
-> 本地或远端 staging
-> 网络 transport
-> 目标设备
虽然 staging 会增加一次拷贝,但它提供兼容性和故障回退。统一 operation 状态机可以把多阶段传输表现为一个用户请求。
十一、故障处理与取消
TENT 测试明显增加了:
failover
engine failover E2E
fault proxy
RDMA cancel
rail monitor
endpoint lifecycle
RPC handler isolation
这反映设计重点从“后端返回错误码”升级为:
- 失败发生在哪个阶段;
- 是否可以切换 rail 或 transport;
- 已完成部分是否需要保留;
- cancel 如何传播到底层;
- callback 是否只触发一次;
- shutdown 是否仍能安全回收资源。
十二、Metastore 与 Control Plane
TENT 把 metastore、RPC 和 control plane 明确分层:
Metastore:Segment 和节点描述
RPC:实时协商与命令
Control Plane:资源、拓扑、选择和故障协调
Data Plane:Transport 实际搬运
支持 etcd、Redis 和 HTTP,使集群部署可以按规模和依赖选择控制面。
十三、Metrics
TENT 有独立 metrics 模块和配置加载,测试覆盖指标记录和 HTTP server。值得观测的维度包括:
- 请求数、字节数和吞吐;
- queueing、submission 和 completion 延迟;
- transport/rail 分布;
- retry、failover 和 cancel;
- receiver credit;
- admission queue 深度;
- deadline miss;
- endpoint 与 Segment 生命周期。
对多路径引擎而言,没有这些指标就很难解释“为什么这次选了 TCP 而不是 RDMA”。
十四、经典 TE 与 TENT 对比
| 维度 | 经典 TE | TENT |
|---|---|---|
| 后端管理 | MultiTransport 中心工厂 | TransportLoader / 插件化 |
| Segment | Metadata 与后端共同管理 | SegmentManager/Registry/Tracker |
| 路径选择 | protocol 与固定优先级 | 拓扑、hint、状态驱动 |
| 进度推进 | 各后端自身 worker | ProgressWorker 统一运行时 |
| QoS | 基础批次与负载信息 | AdmissionQueue + QoSContract |
| 故障 | endpoint 级恢复 | rail、transport、operation 级 failover |
| 接收控制 | 后端自行处理 | Receiver Credit |
| 可观测性 | 分散统计 | 统一 Metrics |
十五、如何阅读和使用两代代码
如果目标是理解 Mooncake 当前广泛使用的数据路径,应先掌握经典 TE:
TransferEngineImpl
-> TransferMetadata
-> MultiTransport
-> RDMA/TCP Transport
如果目标是开发新后端、QoS、容错或动态路由,应重点研究 TENT:
SegmentManager
-> TransportSelector
-> AdmissionQueue
-> ProgressWorker
-> Transport plugin
两代实现目前通过公共门面共存。阅读时必须先确认配置实际启用哪一套,否则看到相同 API 名称却会追到不同执行路径。
十六、系列总结
Mooncake Transfer Engine 的本质不是一个 RDMA wrapper,而是一个异构地址空间传输运行时:
Segment 负责命名和发现
Memory Registration 负责建立访问能力
Transport 负责实际搬运
Batch/Operation 负责异步生命周期
Metadata/RPC 负责控制面
TENT Runtime 进一步负责选择、QoS 与容错
它之所以适合 KV Cache,不是因为理解 KV Cache 内容,而是因为能以较低控制开销搬运大量、可切片、可异步并行的内存区域,并在不同硬件环境下保持统一接口。
参考源码
tent/include/tent/transfer_engine.htent/src/transfer_engine.cpptent/src/runtime/transfer_engine_impl.cpptent/src/runtime/segment_manager.cpptent/src/runtime/segment_registry.cpptent/src/runtime/transport_selector.cpptent/src/runtime/progress_worker.cpptent/src/runtime/admission_queue.cpptent/src/runtime/qos_contract.cpptent/src/runtime/receiver_credit.cpptent/src/runtime/transport_loader.cpp