/v1/loads、routing key 与 placement signal#
这章解决什么问题#
扩展与调试部分已经讲了 metrics、watchdog、request stage、request-level 证据链,但还缺一类对平台工程特别关键的信号:如何从 /v1/loads、routing key 统计、routed_dp_rank 和 worker load metrics 判断系统当前“把请求放到了哪里、负载是不是在往你预期的方向流”。
这一章就是把这些 placement signal 收成一条维护者可用的负载证据链。
为什么这层和普通 metrics 不一样#
普通 metrics 更偏“系统现在忙不忙、快不快”;而 /v1/loads 和 routing signal 更偏“系统把请求分配到了哪里、某类请求是否被聚到一起、当前 worker 之间是否失衡”。这是一层更接近 placement / routing 的观测面。
对多 DP、外部 router、租户隔离或 routing key 场景来说,这层比单纯 TTFT/QPS 更有诊断价值。
一张图:placement signal 来自哪几层#
这张图解决的理解障碍是:很多人会把 /v1/loads 看成单一接口,但它其实综合了 controller、scheduler 和请求对象上的 routing 信息。
flowchart LR
Req["request with routing_key / routed_dp_rank"] --> DPC["DataParallelController"]
DPC --> SCH["scheduler stats / load metrics"]
SCH --> Loads["GetLoadReq / GetLoadsReq -> /v1/loads"]
Req --> Obs["routing key metrics / active gauges"]图比纯文字多解释的一点是:placement signal 不是某个单点 API 生成的,而是请求字段、调度层统计和控制面共同形成的。
/v1/loads 真正提供了什么#
entrypoints/v1_loads.py 与 scheduler_metrics_mixin.py 说明,/v1/loads 不是“再包装一次 Prometheus 指标”,而是提供更接近 scheduler 内部状态的聚合视图。它可以返回:
- core metrics
- memory
- spec
- lora
- disagg
- queues
这使它特别适合作为运行时排障时的“状态快照 API”。
GetLoadsReqInput / GetLoadsReqOutput 为什么值得记#
在 io_struct.py 里,这两个对象明确对应 /v1/loads 这条控制面路径。这说明 load inspection 不是外围工具附加能力,而是 manager 之间正式传递的一种请求/响应对象。
也正因为这样,load 视图可以跨进程、跨 rank 收集,而不是只能在本地线程里临时读变量。
routing key 统计在解释什么#
metrics_collector.py 里会维护:
num_unique_running_routing_keysrouting_key_running_req_countrouting_key_all_req_count
scheduler_metrics_mixin.py 里又会从 running/waiting 请求里提取 routing_key 去计算这些统计。也就是说,系统并不把 routing key 当作纯请求标签,而是把它当成“当前调度分布是否符合预期”的正式观测量。
这对平台工程很重要,因为它能帮助你回答:
- 是否存在某个 routing key 的请求聚集
- 当前运行中的 request cluster 是否偏斜
- waiting queue 和 running batch 的 routing 分布是否一致
routed_dp_rank 与 routing_key 的边界#
它们很容易被混淆,但语义不同:
routed_dp_rank更像“直接指定发到哪个 DP rank”routing_key更像“给调度与观测层一个聚类/亲和信号”
系统同时支持这两个字段,说明它承认“显式 placement 指令”和“软性分布信号”是不同层级的需求。
extract_routed_dp_rank_from_header(...) 为什么关键#
serving_base.py 明确允许从 header 提取 routed_dp_rank,并且优先级高于 body。这说明在真实部署中,路由系统可能并不在请求体里写 placement,而是通过更外层网关或代理注入 header。
这非常值得技术书强调,因为它说明 routing signal 的来源不一定在业务 payload,而可能来自更外层控制平面。
DataParallelController 与 /v1/loads 为什么应该对照看#
前者决定请求被送到哪里,后者则帮助你验证“它现在到底被送到了哪里、各 rank 是否平衡”。如果你只看 controller 逻辑,不看 loads,很容易误以为策略应该没问题;如果你只看 loads,不看 controller,你又很难解释为什么会出现当前分布。
这就是为什么本章要把两者放在一起。
这一层最容易出现的误判#
1. 把 /v1/loads 当成“Prometheus 的另一个壳”#
它更像 scheduler 内部状态的结构化快照接口。
2. 把 routing key 当成业务字段,忽略其调度意义#
实际上系统会显式统计它在 running/waiting 中的分布。
3. 把 routed_dp_rank 当成 load balancing 结果#
很多时候它是外部直接指定的 placement,不是内部策略推导的。
如果你在排查“为什么请求总是去错地方”,先怎么查#
建议按这个顺序:
- 看请求是否带了
routed_dp_rank,来源在 header 还是 body。 - 看是否带了
routing_key。 - 看
DataParallelController当前采用什么LoadBalanceMethod。 - 用
/v1/loads和 related metrics 看各 DP rank、各队列、各 routing key 的分布。 - 最后再决定问题出在外部 router、controller 策略,还是 scheduler 阶段的二次排序。
小结#
这一章真正想补齐的,是维护层里经常被忽略的一类“放置证据”:
/v1/loads讲的是当前状态快照routing_key讲的是请求聚类与调度信号routed_dp_rank讲的是显式 placement 指令
到这里,扩展与调试部分就不仅会告诉你“系统快不快、活不活”,也开始告诉你“请求到底被放到了哪里,以及这种放置是否合理”。
叶王 © 2013-2026 版权所有。如果本文档对你有所帮助,可以请作者喝饮料。