Skip to content

Latest commit

 

History

History
780 lines (630 loc) · 28.5 KB

File metadata and controls

780 lines (630 loc) · 28.5 KB

Rectifiers 详细开发计划

本文档将架构设计中的 8 个 Phase 展开为可按日执行的详细任务。 每个任务标注:优先级、预估工时、前置依赖、产出文件、可验证标准。


P0: 开工前 spike(必须,1-2 天)

在正式编码前,需验证三个关键假设:

验证项 方法 阻塞 Phase
RDMAS v0.1.0 tag 可编译 + pyo3-connector feature 存在 cargo build 直接依赖 git tag P4
LMCache key 的 chunk_hash 格式可被 Router 用 token IDs 复现 手动测试:LMCache key → 提取 chunk_hash → 与 XXH64(token_chunk) 比对 P1, P6
vLLM/SGLang tokenizer.json 可获得并可通过 tokenizers crate 加载 实际下载模型 tokenizer 文件并调用 encode P6

验证通过后,确认版本锁定:

  • RDMAS git tag: v0.1.0
  • LMCache git tag: v0.1.0 (确认后填入)
  • Rust MSRV: 1.80+

总览

Phase 名称 Crate 工时
P0 开工前 spike(版本验证 + hash 对齐) 2 天
P1 Director 核心数据结构 rdmas-director 5 天
P2 Director gRPC 服务 rdmas-director 5 天
P3 Router Python 原型 独立 Python 2.5 天
P4 Connector Director 集成 rectifiers-connector 8 天
P5 Orchestrator 编排层 rdmas-orchestrator 6 天
P6 Router Rust 生产化 rdmas-router 6 天
P7 集成测试 全部 5 天
P8 压测 + 文档 全部 5 天

总计:约 44.5 个工作日(~9 周)(含 P0 spike 2 天)

Phase 依赖图

P1 ──→ P2 ──→ P3 ──→ P4 ──→ P5 ──→ P6 ──→ P7 ──→ P8
              │              │              │
              └── 验证 P1/P2  └── 需要 Director gRPC 就绪

P3(Python 原型)可以在 P2 完成后立即并行启动,验证 Director 的正确性,不阻塞后续 Phase。 P4、P5 可部分并行(分属不同 crate)。


P1: Director 核心数据结构(5 天)

目标:实现 PrefixIndexContextIndexBlockEntry 以及 InstanceRegistry 的内存数据结构,含并发安全、LRU 淘汰、单元测试。

前置依赖:无(纯 Rust 数据结构,不依赖 RDMAS)

任务分解

D1-1: 项目脚手架搭建(0.5 天)

  • 产出文件
    • crates/rdmas-director/Cargo.toml
    • crates/rdmas-director/src/lib.rs
    • Cargo.toml 添加 workspace member
  • 内容:创建 workspace、Cargo.toml 依赖声明(dashmapxxhash-rusttokioserde
  • 验证cargo build -p rdmas-director 成功

D1-2: 实现 ModelContext + BlockEntry(0.5 天)

  • 产出文件
    • crates/rdmas-director/src/types.rs
  • 内容
    pub type NodeId = String;
    pub type InstanceId = String;
    
    pub struct ModelContext {
        pub tenant_id: String,
        pub model_name: String,
        pub block_size: u32,
        pub additional_salt: String,
    }
    
    pub struct BlockEntry {
        pub node_ids: Vec<NodeId>,
        pub access_count: AtomicU64,
        pub last_access: AtomicU64,
    }
  • 验证cargo test 通过(含 Hash/Eq derive 测试)

D1-3: 实现 ContextIndex(1 天)

  • 产出文件
    • crates/rdmas-director/src/context_index.rs
  • 内容
    • ContextIndex 结构体:entries: DashMap<u64, BlockEntry>
    • BlockEntry 使用 RwLock<Vec<NodeId>>(非不可变 Vec)以确保 report_store/report_remove 的并发安全
    • fn report_store(&self, block_hash: u64, node_id: NodeId) — 插入或追加,获取 write lock
    • fn report_remove(&self, block_hash: u64, node_id: NodeId) — 获取 write lock 移除
    • fn query(&self, block_hashes: &[u64]) -> HashMap<NodeId, u32> — 获取 read lock 读取,不重复计数
    • fn evict_lru(&self, max_entries: usize) — LRU 淘汰
  • 边界情况处理
    • 同一个 block_hash 被多次 report_store → node_ids 去重
    • report_remove 后 node_ids 为空 → 删除整个 entry
    • query 空列表 → 返回空 HashMap
  • 验证
    • 单元测试:单 block 插入查询、多 block 聚合、并发插入(多线程)
    • cargo test -p rdmas-director -- context_index

D1-4: 实现 PrefixIndex(1 天)

  • 产出文件
    • crates/rdmas-director/src/prefix_index.rs
  • 内容
    • PrefixIndex 结构体:contexts: DashMap<ModelContext, ContextIndex>
    • fn get_or_create_context(&self, ctx: ModelContext) -> Arc<ContextIndex> — 按 ModelContext 隔离
    • fn report_store(&self, ctx: &ModelContext, block_hash: u64, node_id: NodeId)
    • fn query(&self, ctx: &ModelContext, block_hashes: &[u64]) -> HashMap<NodeId, u32>
    • fn get_stats(&self, ctx: &ModelContext) -> IndexStats — hit_rate 等统计
  • 统计结构 IndexStats
    pub struct IndexStats {
        pub total_blocks: usize,
        pub hit_rate: f64,           // 近期查询命中率(滑动窗口)
        pub prefill_queue_depth: u32, // 注册的 prefill worker 数
        pub decode_queue_depth: u32,  // 注册的 decode worker 数
    }
  • 验证:单元测试验证多 Context 隔离、统计准确性

D1-5: 实现 InstanceRegistry(1 天)

  • 产出文件
    • crates/rdmas-director/src/registry.rs
  • 内容
    pub struct InstanceRegistry {
        instances: DashMap<InstanceId, InstanceInfo>,
    }
    
    pub struct InstanceInfo {
        pub instance_id: InstanceId,
        pub role: InstanceRole,   // Prefill / Decode / Both
        pub node_id: NodeId,      // 附近 RDMAS 节点
        pub rpc_endpoint: String, // vLLM HTTP 地址
        pub dp_rank: u32,
        pub last_heartbeat: AtomicU64,
    }
  • 方法
    • fn register(&self, info: InstanceInfo) — 注册实例
    • fn deregister(&self, instance_id: &str) — 注销
    • fn heartbeat(&self, instance_id: &str) — 更新心跳
    • fn get_nearby_prefills(&self, node_id: &str) -> Vec<InstanceId> — 按 node 查询 prefill
    • fn get_nearby_decodes(&self, node_id: &str) -> Vec<InstanceId> — 按 node 查询 decode
    • fn get_endpoint(&self, instance_id: &str) -> Option<String> — 获取 HTTP 地址
    • fn get_pd_counts(&self) -> (u32, u32) — 当前 P/D 数量
    • fn evict_stale(&self, timeout_ms: u64) — 心跳超时清理
  • 验证
    • 单元测试:注册/查询/心跳/注销/超时清理
    • cargo test -p rdmas-director -- registry

P2: Director gRPC 服务(5 天)

目标:定义 Protobuf 接口,实现 gRPC server,暴露 Query / ReportStore / ReportRemove / Register / Deregister RPC。

前置依赖:P1 完成(依赖 PrefixIndex + InstanceRegistry)

任务分解

D2-1: Protobuf 定义(0.5 天)

  • 产出文件
    • proto/director.proto
  • 内容:按架构设计 §3.4 定义 Director service 及所有 message
  • 验证cargo build 确认 tonic-build 生成代码无报错

D2-2: gRPC Server 骨架(0.5 天)

  • 产出文件
    • crates/rdmas-director/src/server.rs
    • crates/rdmas-director/src/main.rs(独立二进制入口)
  • 内容
    • tonic server 启动,监听 0.0.0.0:9200
    • DirectorService 结构体持有 Arc<PrefixIndex> + Arc<InstanceRegistry>
    • 各 RPC handler 为 unimplemented!() 占位
  • 验证grpcurl -plaintext localhost:9200 list 能看到 service

D2-3: 实现 ReportStore / ReportRemove RPC(1 天)

  • 产出文件
    • crates/rdmas-director/src/report.rs
  • 内容
    • ReportStore: 解析 ReportStoreRequest,调用 PrefixIndex::report_store()
    • ReportRemove: 调用 PrefixIndex::report_remove()
    • 参数校验:empty node_id / block_hash 返回 InvalidArgument
  • 验证:用 grpcurl 发送真实请求,检查 PrefixIndex 内部状态

D2-4: 实现 Query RPC(1 天)

  • 产出文件
    • crates/rdmas-director/src/query.rs
  • 内容
    • Query: 接收 Router 预先计算的 block_hashes,直接查 PrefixIndex → InstanceRegistry → 组装 QueryResponse
    • 注意:Director 不计算 block hashes — Router 预先计算后通过 QueryRequest.block_hashes 发送
  • 验证
    • 预先插入测试数据 → Query 返回正确命中
    • 空 token_ids → 返回空 hits
    • cargo test -p rdmas-director -- query

D2-5: 实现 Register / Deregister / Heartbeat RPC(1 天)

  • 产出文件
    • 更新 crates/rdmas-director/src/registry.rs(gRPC handler 部分)
  • 内容
    • Register: 校验重复注册、解析 role、写入 InstanceRegistry
    • Deregister: 移除实例
    • Heartbeat: 更新 last_heartbeat
  • 验证:注册 → 心跳 → 超时清理 → 注销,完整生命周期测试

D2-6: 集成测试 + 健康检查(1 天)

  • 新增文件
    • crates/rdmas-director/tests/integration_test.rs
  • 内容
    • 启动 Director server → gRPC client 连接 → 完整流程:Register 两个 P + 两个 D → ReportStore 若干 block → Query 返回正确 hits
    • 健康检查 endpoint: grpc.health.v1.Health/Check
  • 验证cargo test -p rdmas-director --test integration_test 全部通过

P3: Router Python 原型(2.5 天)

目标:用 Python FastAPI 实现最简 Router,验证 Director 的正确性和缓存感知调度的效果。不追求性能,只验证功能。

前置依赖:P2 完成(Director gRPC 可用)

任务分解

D3-1: Python 项目搭建(0.5 天)

  • 产出文件
    • prototypes/router-py/requirements.txt
    • prototypes/router-py/main.py
  • 依赖fastapi, uvicorn, grpcio / grpcio-tools, httpx, transformers
  • 验证python main.py 启动成功

D3-2: Director gRPC client(0.5 天)

  • 产出文件
    • prototypes/router-py/director_client.py
  • 内容
    • 加载 Director proto → 生成 Python stub
    • DirectorClient 类封装 query(), report_store(), report_remove()
  • 验证:连上 P2 的 Director server,调用 query() 返回结果

D3-3: 核心路由逻辑(0.5 天)

  • 产出文件
    • prototypes/router-py/router.py
  • 内容
    • tokenize(调 vLLM 的 /tokenize API 或用 transformers
    • 计算 block hashes
    • 调 Director.query()
    • 简单决策:选 matched_blocks 最多的 node → 选该 node 的第一个 worker
    • httpx 转发到 worker
  • 验证:手动 curl 发送 prompt,观察请求被转发到正确的 worker

D3-4: SSE 透传 + 端到端验证(0.5 天)

  • 产出文件
    • prototypes/router-py/stream.py
  • 内容:httpx SSE 流式读取 → StreamingResponse 透传
  • 验证:端到端测试脚本 prototypes/router-py/test_e2e.py

D3-5: 验证报告(0.5 天)

  • 产出文件
    • prototypes/router-py/VERIFICATION.md
  • 内容
    • Director 索引更新及时性
    • 缓存命中 vs 未命中时的路由差异
    • 多 worker 场景下的调度分布
    • 发现的问题和改进点
  • 可选:如果 vLLM 环境不可用,用 mock worker(返回固定 token stream)替代

P4: Connector Director 集成(5 天)

目标:在 RDMAS 已有的 lmcache-connector 中织入 Director 上报逻辑。submit_batch_set 自动调 report_storesubmit_batch_delete 自动调 report_remove

注意:RDMAS 的 lmcache-connector 是上游项目。本 Phase 的实现方式为:在 rectifiers-connector crate 中 wrap 上游 connector 并添加 Director 集成;或者向上游提 PR 添加 feature flag。

前置依赖:P2 完成(Director gRPC 可用),需 RDMAS 仓库可编译

任务分解

D4-1: RDMAS 依赖集成(1 天)

  • 产出文件
    • crates/rectifiers-connector/Cargo.toml(依赖 rdmas git dep)
  • 内容
    • Cargo.toml 中声明 rdmas = { git = "https://github.com/ipconfiger/rdmas", tag = "v0.1.0", features = ["pyo3-connector"] }
    • 验证能编译通过、link 到 libibverbs
  • 验证cargo build -p rectifiers-connector 成功

D4-2: Director gRPC Client(1 天)

  • 产出文件
    • crates/rectifiers-connector/src/director_client.rs
  • 内容
    • tonic gRPC client 连接 Director :9200
    • DirectorClient 封装 report_store, report_remove
    • 连接重试 + 超时处理
  • 验证:单元测试 mock Director server

D4-3: submit_batch_set/drain_completions 织入 report_store(1.5 天)

  • 产出文件
    • crates/rectifiers-connector/src/connector.rs
  • 内容
    • 阶段 1(submit_batch_set):记录 pending 元数据 future_id → (node_id, block_hashes, ctx),不立即上报
    • 阶段 2(drain_completions):仅在 comp.ok == true 时调 director_client.report_store()
    • report_store 调用为 tokio::spawn fire-and-forget,失败时 tracing::warn 记录
  • 关键保证:RDMA 写入成功后 Director 才知道该 block 存在,避免 phantom cache hits

D4-4: submit_batch_delete 织入 report_remove + 配置(1 天)

  • 产出文件
    • crates/rectifiers-connector/src/config.rs
  • 内容
    • 同 D4-3,submit_batch_deletereport_remove
    • 配置结构:
      pub struct RectifiersConfig {
          pub director_addr: Option<String>, // "127.0.0.1:9200"
          pub node_id: String,
          pub tenant_id: String,
          pub model_name: String,
          pub block_size: u32,
      }
    • 从 LMCache adapter_params JSON 解析配置
  • 验证:集成测试:配置 director_addr → 调 submit_batch_set → 验证 Director 收到 report

D4-5: PyO3 暴露 + 端到端验证(1 天)

  • 产出文件
    • crates/rectifiers-connector/src/lib.rs(PyO3 entrypoint)
  • 内容
    • 导出增强版 RDMANativeConnector pyclass
    • 支持 adapter_params 中的 director_addr 字段
    • 端到端测试:Python 侧调 submit_batch_set → Rust 侧走完整链路 → Director 收到上报
  • 验证:Python 测试脚本 + cargo test -p rectifiers-connector

P5: Orchestrator 编排层(5 天)

目标:实现 auto_tune_loop 决策循环、vLLM reconfigure 调用、stats 收集与暴露。

前置依赖:P2 完成(Director gRPC 可用)

任务分解

D5-1: Orchestrator 脚手架(0.5 天)

  • 产出文件
    • crates/rdmas-orchestrator/Cargo.toml
    • crates/rdmas-orchestrator/src/lib.rs
    • crates/rdmas-orchestrator/src/main.rs
  • 依赖rdmas-director(local path dep), tokio, reqwest, serde
  • 验证cargo build -p rdmas-orchestrator

D5-2: Director stats 采集(1 天)

  • 产出文件
    • crates/rdmas-orchestrator/src/stats.rs
  • 内容
    • StatsCollector 结构体,周期性(30s)调 Director gRPC 获取 stats
    • 采集指标:
      pub struct SystemStats {
          pub hit_rate: f64,
          pub prefill_count: u32,
          pub decode_count: u32,
          pub prefill_queue_depth: u32,
          pub decode_queue_depth: u32,
      }
  • 验证:mock Director → 验证 stats 采集正确

D5-3: auto_tune 决策循环(1.5 天)

重要:vLLM 无运行时角色切换 HTTP API。Orchestrator 通过 K8s API 调整独立 Prefill/Decode Deployment 副本数。

  • 产出文件
    • crates/rdmas-orchestrator/src/decision.rs
  • 内容
    pub struct AutoTuner {
        config: AutoTuneConfig,
        director: DirectorClient,
        k8s_client: K8sClient,
    }
    
    impl AutoTuner {
        async fn evaluate(&self, stats: &SystemStats) -> Option<Action> {
            if stats.hit_rate < self.config.hit_rate_threshold_up
               && stats.prefill_count < self.config.max_prefill
            {
                Some(Action::ScalePrefillUp)
            } else if stats.hit_rate > self.config.hit_rate_threshold_down
                      && stats.decode_count < self.config.max_decode
            {
                Some(Action::ScaleDecodeUp)
            } else {
                None
            }
        }
    
        async fn execute(&self, action: Action) -> Result<()> {
            match action {
                Action::ScalePrefillUp => {
                    self.k8s_client.scale("vllm-prefill", +1).await?;
                    self.k8s_client.scale("vllm-decode", -1).await?;
                }
                Action::ScaleDecodeUp => {
                    self.k8s_client.scale("vllm-decode", +1).await?;
                    self.k8s_client.scale("vllm-prefill", -1).await?;
                }
            }
            Ok(())
        }
    }
  • hysteresis 防震荡:连续 3 次评估都触发才执行切换
  • 验证:单元测试覆盖各种 stats 组合 → 验证决策正确性

D5-4: K8s 扩缩执行(1 天)

  • 产出文件
    • crates/rdmas-orchestrator/src/k8s.rs
  • 内容
    • K8sClient 封装 K8s API → 调整 Deployment replica 计数
    • 扩缩前校验:不低于 min_prefill/min_decode,不超过 max_prefill/max_decode
    • 支持 dry-run 模式(mode A: 纯建议,不执行)
    • 新 Pod 启动后自动通过 Connector 调 Director.Register(),无需 Orchestrator 介入
  • 验证:mock K8s API server → 验证 scale 请求格式正确

D5-5: Orchestrator gRPC API(0.5 天)

  • 产出文件
    • proto/orchestrator.proto
  • 内容GetPDRatio, SetPDRatio, GetRecommendation RPC
  • 实现:读取 Director InstanceRegistry 的 P/D 计数
  • 验证:grpcurl 调用

D5-6: 配置热加载 + 日志(0.5 天)

  • 产出文件
    • crates/rdmas-orchestrator/src/config.rs
  • 内容
    • JSON 配置文件解析(rectifiers_config.json
    • tracing 结构化日志:决策日志包含 reason + before/after stats
  • 验证:修改配置 → 重启生效 / SIGHUP 热加载

P6: Router Rust 生产化(5 天)

目标:用 Rust 重写 P3 的 Python 原型,实现 tokenizer 集成、多因素决策、HTTP dispatch、SSE stream。

前置依赖:P2 完成,P5 完成(需 Director + Orchestrator gRPC 就绪)

任务分解

D6-1: Router 脚手架 + HTTP server(0.5 天)

  • 产出文件
    • crates/rdmas-router/Cargo.toml
    • crates/rdmas-router/src/main.rs
  • 依赖axum, rdmas-director(local path dep), tokenizers, reqwest, xxhash-rust
  • 验证cargo build -p rdmas-router 成功,/health 返回 200

D6-2: Tokenizer 集成(1 天)

  • 产出文件
    • crates/rdmas-router/src/tokenize.rs
  • 内容
    • 加载 tokenizer.json(从 HuggingFace model repo 下载或本地路径)
    • TokenizerService 结构体:
      pub struct TokenizerService {
          tokenizer: tokenizers::Tokenizer,
          block_size: u32,
      }
      
      impl TokenizerService {
          pub fn encode(&self, prompt: &str) -> Vec<u64> { ... }
          pub fn compute_block_hashes(&self, token_ids: &[u64]) -> Vec<u64> {
              token_ids.chunks(self.block_size as usize)
                  .map(|c| xxhash_rust::xxh3::xxh3_64(c))
                  .collect()
          }
      }
  • 错误处理:tokenizer 未加载 → 启动失败,明确报错
  • 验证:单元测试验证 encode + hash 结果与 Python transformers 一致

D6-3: Director gRPC client(0.5 天)

  • 产出文件
    • crates/rdmas-router/src/director.rs
  • 内容
    • tonic gRPC client 连接 Director :9200
    • 连接池 + 健康检查
  • 验证:集成测试连 P2 的 Director server

D6-4: 多因素决策算法(1 天)

  • 产出文件
    • crates/rdmas-router/src/decision.rs
  • 内容
    • 将 §5.3 的 select_best_worker() 算法从原型翻译为正式实现
    • 增加:worker 负载追踪(滑动窗口 active_requests 计数)
    • 增加:超时降级(Director 超时 → 随机选一个可用 worker)
  • 验证:单元测试覆盖各种 hits 组合

D6-5: HTTP dispatch + SSE stream(1.5 天)

  • 产出文件
    • crates/rdmas-router/src/proxy.rs
    • crates/rdmas-router/src/stream.rs
  • 内容
    • POST /v1/chat/completions handler
    • 请求解析 → tokenize → hash → Director query → 决策 → reqwest 转发
    • SSE stream 透传(axum::response::Sse
    • OpenAI 兼容 API 格式(choices[0].delta.content
    • 错误映射:Director 超时 → 503,无可用 worker → 503
  • 验证:curl 发送请求 → 收到 SSE token stream

D6-6: 配置 + tracing + metrics(0.5 天)

  • 产出文件
    • crates/rdmas-router/src/config.rs
  • 内容
    • JSON 配置文件:director_addr, tokenizer_path, block_size, listen_addr
    • tracing span:request_idtokenizedirector_querydecisiondispatchstream
    • metrics:request_count, hit_rate, dispatch_latency_histogram
  • 验证/metrics 暴露 Prometheus 指标

P7: 集成测试(5 天)

目标:全部子系统联调,含 mock RDMAS 节点和 mock vLLM worker,验证完整数据流。

前置依赖:P1-P6 全部完成

任务分解

D7-1: Mock RDMAS 节点(1 天)

  • 产出文件
    • tests/mock_rdmas.rs
  • 内容
    • 实现 KvEngine trait 的 mock(内存 HashMap 后端)
    • 模拟 ControlPlane gRPC server(Discover / Heartbeat)
  • 验证:mock 可被 Connector 作为 KvEngine 使用

D7-2: Mock vLLM Worker(1 天)

  • 产出文件
    • tests/mock_vllm.rs
  • 内容
    • HTTP server 模拟 vLLM OpenAI API
    • /tokenize → 返回 mock token_ids
    • /generate → 返回固定 SSE token stream
    • /admin/reconfigure → 接受角色切换请求
  • 验证:Router 能成功 dispatch 到 mock

D7-3: 端到端流程测试(2 天)

  • 产出文件
    • tests/e2e_test.rs
  • 测试场景
    1. 冷启动:无缓存 → Router dispatch 到 prefill → prefill 写入 RDMAS → Connector 上报 Director → Director 索引更新
    2. 热缓存命中:相同 prompt 再次请求 → Director 返回 high hits → Router dispatch 到 decode → decode 从 RDMAS 读取 KV cache
    3. P:D 动态切换:模拟 hit_rate 下降 → Orchestrator 触发 reconfigure → 一个 D 转为 P → 验证 Director 注册更新
    4. Worker 故障:一个 worker 不可用 → Router 降级到次优 worker → 请求仍然完成
    5. 多 tenant 隔离:不同 tenant_id 的 model context 不互相干扰
  • 验证cargo test --test e2e_test 全部通过

D7-4: 故障注入测试(1 天)

  • 产出文件
    • tests/fault_test.rs
  • 测试场景
    1. Director 宕机重启 → Router 重连 + 请求恢复
    2. RDMAS 节点网络分区 → Connector 超时处理
    3. Orchestrator 误判 → hysteresis 防止震荡
    4. 大量并发注册 → InstanceRegistry 竞态安全
  • 验证:所有故障场景有预期行为(非 panic)

P8: 压测 + 文档(5 天)

目标:性能基准测试、LMCache 真实集成验证、部署文档、最终交付。

前置依赖:P7 完成

任务分解

D8-1: 性能基准测试(1.5 天)

  • 产出文件
    • benches/director_bench.rs
    • benches/router_bench.rs
  • 内容
    • Director: 100 万 block 索引 → Query 延迟 P50/P99
    • Router: tokenize + query + decision → 端到端延迟(不含模型推理)
    • 并发测试:100 并发 gRPC → Director throughput
    • 内存占用:100 万 blocks 的内存 RSS
  • 验证:Report 产出性能数据,与 §性能目标 对比

D8-2: LMCache 真实集成(1 天)

  • 内容
    • 在真实 vLLM + LMCache 环境中部署 Rectifiers Connector
    • 验证 LMCache L2 后端可正确使用 RDMAS 存储
    • 验证 Director 收到来自真实 Connector 的 report_store 上报
  • 产出文件
    • examples/lmcache_vllm_config.json
  • 验证:vLLM 推理请求成功通过 Rectifiers 全链路

D8-3: Docker 化部署(1 天)

  • 产出文件
    • docker/Dockerfile.director
    • docker/Dockerfile.router
    • docker/Dockerfile.orchestrator
    • docker/docker-compose.yml(全套本地开发环境)
  • 内容
    • 多阶段构建,最终镜像 < 100MB
    • docker-compose 一键启动:RDMAS nodes + Director + Router + Orchestrator + mock vLLM
  • 验证docker-compose up 全部服务 healthy

D8-4: 文档完善(1 天)

  • 产出文件
    • README.md(项目概览 + 快速开始)
    • docs/deployment.md(生产部署指南)
    • docs/lmcache-integration.md(LMCache 集成步骤)
    • docs/api.md(gRPC API 参考)
  • 验证:按文档步骤可从零开始部署

D8-5: CI/CD Pipeline(0.5 天)

  • 产出文件
    • .github/workflows/ci.yml
  • 内容
    • cargo test 全部 crate
    • cargo clippy -- -D warnings
    • cargo fmt --check
    • cargo build --release
  • 验证:PR 触发 CI 通过

附录 A:风险缓解时间线

风险 Phase 检查点 若失败则
RDMAS 接口漂移 P4 cargo build 编译不过 锁定旧版 git tag
LMCache native_plugin 接口不兼容 P4 PyO3 导出签名对不上 适配或等待上游
tokenizers crate 加载模型失败 P6 tokenizer.json 格式/路径 回退到调 vLLM tokenize API
Director 内存膨胀 P8 压测 100 万 entries 内存 > 500MB 加 LRU 淘汰 + Bloom filter

附录 B:文件清单

rectifiers/
├── Cargo.toml
├── crates/
│   ├── rdmas-director/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── lib.rs
│   │       ├── main.rs              # gRPC server 入口
│   │       ├── types.rs             # ModelContext, BlockEntry, NodeId
│   │       ├── context_index.rs     # ContextIndex
│   │       ├── prefix_index.rs      # PrefixIndex
│   │       ├── registry.rs          # InstanceRegistry
│   │       ├── query.rs             # Query gRPC handler + block hash 计算
│   │       ├── report.rs            # ReportStore/ReportRemove gRPC handler
│   │       ├── server.rs            # tonic server 启动
│   │       └── stats.rs             # IndexStats
│   │
│   ├── rdmas-router/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── lib.rs
│   │       ├── main.rs              # axum HTTP server 入口
│   │       ├── config.rs            # RouterConfig
│   │       ├── tokenize.rs          # TokenizerService
│   │       ├── director.rs          # Director gRPC client
│   │       ├── decision.rs          # select_best_worker()
│   │       ├── proxy.rs             # HTTP dispatch to worker
│   │       └── stream.rs            # SSE stream 透传
│   │
│   ├── rdmas-orchestrator/
│   │   ├── Cargo.toml
│   │   └── src/
│   │       ├── lib.rs
│   │       ├── main.rs
│   │       ├── config.rs            # AutoTuneConfig
│   │       ├── stats.rs             # StatsCollector
│   │       ├── decision.rs          # AutoTuner::evaluate()
│   │       └── reconfigure.rs       # VllmClient
│   │
│   └── rectifiers-connector/
│       ├── Cargo.toml               # cdylib, dep: rdmas (git)
│       └── src/
│           ├── lib.rs               # PyO3 entrypoint
│           ├── config.rs            # RectifiersConfig
│           ├── director_client.rs   # Director gRPC client
│           └── connector.rs         # Wrap + report_store/remove 织入
│
├── proto/
│   ├── director.proto
│   └── orchestrator.proto
│
├── prototypes/
│   └── router-py/
│       ├── requirements.txt
│       ├── main.py
│       ├── director_client.py
│       ├── router.py
│       ├── stream.py
│       ├── test_e2e.py
│       └── VERIFICATION.md
│
├── tests/
│   ├── mock_rdmas.rs
│   ├── mock_vllm.rs
│   ├── e2e_test.rs
│   └── fault_test.rs
│
├── benches/
│   ├── director_bench.rs
│   └── router_bench.rs
│
├── docker/
│   ├── Dockerfile.director
│   ├── Dockerfile.router
│   ├── Dockerfile.orchestrator
│   └── docker-compose.yml
│
├── examples/
│   └── lmcache_vllm_config.json
│
├── .github/workflows/
│   └── ci.yml
│
└── docs/
    ├── architecture.md
    ├── development-plan.md      # 本文档
    ├── deployment.md
    ├── lmcache-integration.md
    └── api.md