预计阅读 5 分钟

生产 7:Router 与 SGLang Model Gateway

谁该读这一篇? 要在多个 SGLang worker 前置路由、配置 cache-aware/负载策略,或搭建 PD/gRPC/多模型网关的工程师。 前置阅读: 05-distributed/02-data-parallelism.md。

1. 组件选择

当前仓库有两个相关实现:

组件 适用场景 入口
experimental/sgl-router 单模型、静态 URL 或 Kubernetes EndpointSlice sgl-router Rust binary
sgl-model-gateway 多模型(IGW)、PD、HTTP/gRPC、OpenAI 后端、重试/熔断/历史/MCP sgl-model-gateway 或 python3 -m sglang_router.launch_router

两者都提供 OpenAI 兼容 API 和 /metrics;不要再使用旧的 pip install sgl-router 或 --worker-weights 示例,安装方式以对应目录的 README/发行包为准。

2. 最小拓扑

Client ─▶ Router/Gateway ──┬─▶ SGLang worker 1
                           ├─▶ SGLang worker 2
                           └─▶ SGLang worker N

Router 只负责请求路由和可靠性;每个 worker 独立持有 GPU KV cache。cache-aware 信号来自 router 的 prefix tree 或外部 KV indexer,不是把 GPU KV 复制到 router。

3. Experimental sgl-router

从源码构建并运行:

cd sglang/experimental/sgl-router
cargo build --release
./target/release/sgl-router \
  --host 0.0.0.0 --port 30000 \
  --model-id qwen3 \
  --tokenizer-path /models/qwen3/tokenizer.json \
  --worker-urls http://10.0.0.1:30000 http://10.0.0.2:30000

也可省略 --tokenizer-path,让 router 根据 --model-id 从 HuggingFace 下载 tokenizer(需要网络和 HF_TOKEN/HF_HOME 配置)。Kubernetes 场景使用 --service-discovery、--service-discovery-namespace 和 --selector;PD 拓扑则 分别使用 --prefill-selector 与 --decode-selector。

外部 KV indexer 示例:

./target/release/sgl-router \
  --model-id qwen3 --tokenizer-path /models/qwen3/tokenizer.json \
  --worker-urls http://10.0.0.1:30000 http://10.0.0.2:30000 \
  --policy cache_aware_zmq \
  --kv-indexer-endpoint http://10.0.0.10:50051 \
  --kv-indexer-query-timeout-ms 100 \
  --kv-indexer-query-max-inflight 32

indexer 查询超时、连接失败或服务端拒绝会返回 503;不会静默切换到另一个 缓存信号。完整参数以 sgl-router --help 为准。

3.1 三类信号不要混淆

当前 worker 能暴露三类不同信息:

  1. KV placement event 描述 block 存入、移除或清空,供 router/indexer 重建缓存位置;
  2. 外部 KV indexer 回答“某个 prompt 的 block 在哪些 worker”;
  3. 可选 runtime-load socket 发布每个 scheduler 的 num_running_reqs、 num_waiting_reqs、KV 已用 token、KV 容量和 rank。

第 3 类通过 worker 的 --load-publish-endpoint auto 显式开启,默认关闭,并且要求 同时配置 --kv-events-config。auto 在 KV event 端口范围后为每个 DP rank 分配 load 端口;/server_info 的 kv_events block 会返回 load_endpoint_port_base 与 load_topic。发布周期复用 --load-snapshot-publish-interval,实际部署要给同机 worker 的端口范围留足间隔。

这是一条供进程外 load-aware router 使用的 ZMQ PUB 协议,不等于 bundled experimental router 的外部 indexer 查询,也不改变上面的 503 语义。消费者必须 显式支持 LoadStat wire format;发布或订阅异常时应回退到自身维护的 in-flight 负载信号,而不能把陈旧 gauge 当成当前 scheduler 状态。

源码:load_publisher.py:72、 server_args.py:1598。

4. SGLang Model Gateway

cd sglang/sgl-model-gateway
cargo build --release
./target/release/sgl-model-gateway \
  --worker-urls http://worker1:8000 http://worker2:8000 \
  --policy cache_aware

开发或 Python launcher:

python3 -m sglang_router.launch_router \
  --worker-urls http://worker1:8000 http://worker2:8000 \
  --policy cache_aware

PD 路由可以独立指定 prefill/decode 策略:

./target/release/sgl-model-gateway \
  --pd-disaggregation \
  --prefill http://prefill1:30001 9001 \
  --decode http://decode1:30011 \
  --policy cache_aware --prefill-policy cache_aware --decode-policy power_of_two

多模型 inference gateway(IGW)通过 worker registry 动态登记:

./target/release/sgl-model-gateway --enable-igw --policy cache_aware
curl -X POST http://localhost:30000/workers \
  -H 'Content-Type: application/json' \
  -d '{"url":"http://worker-a:8000","model_id":"qwen3","priority":10}'
curl http://localhost:30000/workers

5. 路由策略

Model Gateway 当前支持:

策略 行为 适合
random 均匀随机选择 基线/测试
round_robin 轮询 无缓存收益的简单服务
cache_aware prefix tree + 阈值做重复 prompt 复用,并在失衡时平衡 共享 system prompt
power_of_two 随机抽两个 worker,选负载较低者 负载波动明显
bucket 按 bucket/DP 亲和性选择 需要固定分组

cache_aware 是近似的路由决策:真实 KV 仍在 worker GPU,树状态会变化, 因此它不是一致性或正确性保证。可调参数包括 --cache-threshold、 --balance-abs-threshold、--balance-rel-threshold、--eviction-interval 和 --max-tree-size。

6. 健康、重试与故障切换

Gateway 提供 /liveness、/readiness、/health、/health_generate;readiness 会检查健康 worker,PD 模式还要检查 prefill/decode 配对。生产探针应给 CUDA Graph capture 和模型加载留足启动时间。

Gateway 的数据面包含每 worker circuit breaker、指数退避重试(带 jitter)、 token bucket 与可选 FIFO 请求队列,以及 PD worker 的 /flush_cache 管理。 请求中途失败时 router 不会无条件 replay 有状态请求;客户端仍应使用带 jitter 的有限重试,并保证幂等键/会话语义。

7. API 与观测

常用接口包括 /v1/chat/completions、/v1/responses、/v1/embeddings、 /v1/rerank、/v1/classify,以及 /v1/tokenize//v1/detokenize。gRPC 模式在 router 本地完成 tokenizer、reasoning parser 和 tool parser,再将流式 请求发送到 SRT gRPC worker。

启用 Prometheus(gateway 默认监听 0.0.0.0:29000):

./target/release/sgl-model-gateway \
  --worker-urls http://worker1:8000 \
  --prometheus-host 0.0.0.0 --prometheus-port 29000

重点关注 smg_router_*、smg_worker_*、smg_worker_cb_*、 smg_worker_retries_* 和 smg_discovery_*;SGLang worker 自身的 sglang:* 指标见 03-monitoring.md。

8. 排查清单

现象 检查
cache-aware 命中下降 eviction、tree 大小、max-tree-size,必要时切 power_of_two
流量长期倾斜 cache-aware 的倾斜可能是预期;比较 worker load,再调 balance 阈值
worker 被摘除 /health、熔断器状态、连续失败次数和连接超时
PD 请求 503 prefill/decode 是否都 ready,bootstrap port 和 selector 是否匹配
gRPC 请求失败 tokenizer/model path、reasoning/tool parser 与 worker 能力是否一致
router CPU 高 请求量、tree 大小和 discovery 刷新频率,增加 gateway 副本

9. 小结

  • 单模型静态路由可用 experimental sgl-router;多模型、PD、gRPC 和可靠性能力优先使用 sgl-model-gateway。
  • cache_aware 使用 prefix/tree 信号做路由近似,不共享 GPU KV,也不是 Bloom filter API 的承诺。
  • 灰度应在 Kubernetes/service mesh 或独立 worker pool 层完成;当前 CLI 没有可依赖的 --worker-weights 合同。
  • 健康检查、熔断、重试、Prometheus 和 OpenTelemetry 应作为生产配置的一部分。

10. 自检

  1. Router 是否持有 RadixCache 的 KV?

不持有。KV 在 worker 的设备/层级缓存中;router 只维护 prefix/tree 或 indexer 查询结果。

  1. 外部 KV indexer 查询失败时会发生什么?

cache_aware_zmq 会将失败、超时或服务端拒绝报告为 503,不会静默使用过期或不同来源的信号。

  1. 什么时候选 power_of_two 而不是 cache_aware?

prompt 重复率低、worker 负载差异大,或缓存树维护成本超过收益时,power_of_two 通常更合适。

11. 下一步