执行摘要
该 PR 为 experimental sgl-router 新增了 /flush_cache 管理端点,允许运维人员一次性刷新所有 worker 的 KV 缓存。实现包含新的路由处理文件、注册表扩展、路由挂载和单元测试。这是一个标准的管理功能添加,设计上考虑了并发限制、错误报告和断路器绕过,但存在无法区分延迟刷新以及可能影响断路器状态的风险。
功能与动机
根据 PR body,该功能的动机是 'Add an endpoint to flush the cache for all the workers to the experimental router',目的是提供一个中心化的缓存刷新接口,避免运维人员逐一登录 worker 操作。这与 sgl-model-gateway 中的 /flush_cache 功能一致。
实现拆解
- 新增路由处理文件
experimental/sgl-router/src/server/routes/cache.rs,定义了 FlushCacheResult 和 FailedWorker 序列化结构体,核心函数 flush_cache 获取全量 worker 并调用 fan_out_flush 并发发送 POST 请求。fan_out_flush 使用 buffer_unordered(32) 限制并发,并直接使用共享 reqwest::Client 绕过断路器。
- 扩展 WorkerRegistry 在
experimental/sgl-router/src/workers/registry.rs 中添加 pub fn all(&self) -> Vec<Arc<Worker>> 方法,返回所有注册 worker 的克隆列表(包括不同模式和模型的 worker)。同时新增两个单元测试验证跨模式全量返回和空注册表行为。
- 挂载路由 在
experimental/sgl-router/src/server/app.rs 的 build_router 中通过 .route("/flush_cache", post(crate::server::routes::cache::flush_cache)) 注册新端点。
- 导出模块 在
experimental/sgl-router/src/server/routes/mod.rs 中添加 pub mod cache; 声明。
- 测试覆盖 在
cache.rs 中包含了 10 个测试用例,包括全部成功返回 200、部分失败返回 502 并带 breakdown、空 fleet、不可达 worker、非 5xx 状态(如 404)处理、尾部斜杠 URL、以及不同模式 worker 等场景。
experimental/sgl-router/src/workers/registry.rs
基础数据结构扩展:新增 all() 方法,支持全量 worker 快照,是 fan-out 的前提。
/// Snapshot of every registered worker, across all models and modes.
/// Used by fleet-wide admin fan-out (e.g. `/flush_cache`) that targets
/// every worker the router knows about rather than one model's pool.
/// Order is unspecified (iterates the underlying `DashMap`).
pub fn all(&self) -> Vec<Arc<Worker>> {
self.by_id.iter().map(|e| Arc::clone(e.value())).collect()
}
对应的测试:
#[test]
fn all_returns_every_worker_across_models_and_modes() {
let r = WorkerRegistry::default();
let _ = r.add(spec("w1", WorkerMode::Plain, &["m1"]));
let _ = r.add(spec("p", WorkerMode::Prefill, &["m2"]));
let _ = r.add(spec("d", WorkerMode::Decode, &["m2"]));
let mut ids: Vec<String> = r.all().into_iter().map(|w| w.id.0.clone()).collect();
ids.sort();
assert_eq!(ids, vec!["d", "p", "w1"]);
}
#[test]
fn all_is_empty_for_fresh_registry() {
assert!(WorkerRegistry::default().all().is_empty());
}
评论区精华
当前 PR 没有 review 评论,但 PR body 中详细说明了两个关键设计决策:
- 绕过断路器:管理刷 nova 需要触及每个 worker,包括断路器打开的 worker;同时避免在断路器状态中记录管理操作。
- 已知局限:SGLang worker 的
/flush_cache 在等待现有请求时会返回 200 但延迟执行,本端点无法区分立即成功和延迟执行,任何非 400 响应视为成功。
风险与影响
- 风险:
- 绕过断路器可能使运维人员忽略 worker 的实际健康状态,并可能干扰断路器的正常状态机。
- 无法区分延迟刷新,运维人员可能误判操作效果。
- 缺少对数千 worker 集群的并发测试,可能出现超时。
- 影响:仅影响 experimental 路由器的管理接口,不影响核心请求路径;需要适当网络隔离以防止未授权访问。
关联脉络
该 PR 是 experimental router 管理能力补全的一部分,与 sgl-model-gateway 的 /flush_cache 功能对标。近期仓库中也有多个管理/运维相关的 PR(如 #27363 添加指标),表明团队在增强 SGLang 的可运维性。
参与讨论