# PR #25294 完整报告

- 仓库：`sgl-project/sglang`
- 标题：[SMG] Support regular worker discovery alongside PD workers in IGW mode
- 合并时间：2026-05-21 07:23
- 原文链接：http://prhub.com.cn/sgl-project/sglang/pull/25294

---

## 执行摘要

本次 PR 为 sgl-model-gateway 的服务发现模块增加了对 **混合 PD + 常规 worker**的支持。在启用 `--enable-igw` 后，路由器可以同时发现分离部署的 prefill/decode worker 以及常规 worker，使得单一路由器能够服务多种模型。该变更不引入新 CLI 参数，通过组合已有参数实现，并增加了配置不当的告警机制。

## 功能与动机

当使用 `--pd-disaggregation` 时，服务发现只接受匹配 `prefill_selector` 或 `decode_selector` 的 Pod。匹配 `--selector`（常规 worker）的 Pod 被静默丢弃，导致无法从同一路由器同时服务多个模型（一些通过 PD，一些通过常规路由）。在 IGW 模式下，`RouterManager` 已同时创建 Regular 和 PD 路由器并按 worker 类型分发请求——路由基础设施支持混合调度，但服务发现缺失了常规 worker 的发现能力。详见 PR body。

## 实现拆解

1. **数据结构扩展 **(`sgl-model-gateway/src/service_discovery.rs`)：在 `ServiceDiscoveryConfig` 中新增 `igw_mode: bool` 字段，默认 `false`，确保向后兼容。
2. **核心服务发现逻辑调整 **(`service_discovery.rs`)：修改 `PodInfo::should_include()` 方法，在 `pd_mode=true` 且 `igw_mode=true` 时，额外检查 Pod 是否匹配 `--selector`，若匹配则归入 `PodType::Regular`。同时修复了当 `prefill_selector` 和 `decode_selector` 都为空时早期返回导致常规 worker 被忽略的问题。新增 `warn_if_misconfigured()` 方法，当 `pd_mode` 和 `selector` 已设但 `igw_mode` 未启用时输出告警。
3. **入口集成 **(`main.rs` 和 `bindings/python/src/lib.rs`)：在 CLI 入口和 Python 绑定的配置构造处，将 `enable_igw` 传入 `igw_mode`，并在构造完成后调用 `warn_if_misconfigured()` 统一告警。

### `sgl-model-gateway/src/service_discovery.rs`

核心文件，实现服务发现配置扩展、should_include 多模式判断、配置告警以及大量单元测试。

```rust
// ServiceDiscoveryConfig 新增 igw_mode 字段，当启用 IGW 时允许同时发现常规 worker
impl ServiceDiscoveryConfig {
    pub fn warn_if_misconfigured(&self) {
        // 若 PD 模式已开启但未启用 IGW，且设置了 --selector，则发出告警
        if self.pd_mode && !self.igw_mode && !self.selector.is_empty() {
            warn!(
                "--selector is set in PD mode without IGW mode enabled; \
                regular worker discovery alongside PD workers requires IGW mode, \
                selector will be ignored"
            );
        }
    }
}

impl PodInfo {
    pub fn should_include(pod: &Pod, config: &ServiceDiscoveryConfig) -> bool {
        if config.pd_mode {
            // 当 prefill 和 decode selector 都为空时，仅在 IGW+selector 模式下不提前返回
            if config.prefill_selector.is_empty() && config.decode_selector.is_empty() {
                if !(config.igw_mode && !config.selector.is_empty()) {
                    warn!("PD mode enabled but both prefill_selector and decode_selector are empty");
                    return false;
                }
            }
            let matches_pd = Self::matches_selector(pod, &config.prefill_selector)
                || Self::matches_selector(pod, &config.decode_selector);
            // IGW 模式下，额外匹配 --selector 对应的常规 worker
            let matches_regular = config.igw_mode
                && !config.selector.is_empty()
                && Self::matches_selector(pod, &config.selector);
            matches_pd || matches_regular
        } else {
            // 常规非 PD 模式，与原有逻辑一致
            if config.selector.is_empty() {
                warn!("Regular mode enabled but selector is empty");
                return false;
            }
            Self::matches_selector(pod, &config.selector)
        }
    }
}

```

## 评论区精华

- **Reviewer alexnails**指出 `should_include()` 中当 `prefill_selector` 和 `decode_selector` 均为空时，原逻辑直接返回 false，导致 `matches_regular` 分支不可达，建议调整条件以支持 IGW+selector 模式。（已修复）
- **alexnails**还发现告警仅出现在二进制入口（`main.rs`），而 Python 绑定入口缺失，建议统一。开发者通过抽取 `warn_if_misconfigured()` 方法并在两入口调用解决了问题。（已修复）

## 风险与影响

- **风险**：`igw_mode` 默认为 false，不对现有 PD 模式产生影响，向后兼容性良好。唯一的新风险是用户在 PD+IGW 模式下未设置 `--selector` 时不会发现常规 worker，但系统不会出错且会有告警提示。
- **影响**：主要影响使用了 `--pd-disaggregation` 和 `--enable-igw` 的部署场景。用户无需更改现有配置即可获得混合发现能力。对性能无影响。

## 关联脉络

本 PR 是 sgl-model-gateway 中 IGW 功能完整性的重要补充。历史 PR 中已有多次对服务发现和路由能力的改进（如 #25862 对 FutureMap 重构、#25741 分块预填充修复、#25101 可插拔 RadixCache），本 PR 与其无直接代码冲突，共同完善了网关层的路由与服务发现能力。