执行摘要
- 一句话:同步多节点 prefill bootstrap 端口,修复跨节点注册失败
- 推荐动作:此 PR 修复了多节点 disagg 部署中的静默故障,设计简洁高效。建议阅读
_sync_bootstrap_port_across_nodes 方法,了解如何使用 torch.distributed.broadcast_object 实现跨节点配置同步,这种 Leader 广播模式在分布式系统中很有参考价值。
功能与动机
在 multi-node disaggregated prefill 中,每个 prefill scheduler 进程解析自己的 server_args.disaggregation_bootstrap_port。某些启动器(如 Dynamo)会在启动时自动保留空闲端口,导致各主机端口不同。register_to_bootstrap 虽然主机地址正确解析自 dist_init_addr(world-rank 0),但端口使用本地端口,非 leader 节点因此向 leader 的本地端口发送请求,而 leader 在该端口没有监听,导致 Connection refused 和后续的 KeyError 及 AttributeError。当前 workaround 是手动指定固定端口,但默认路径静默失败。
实现拆解
实现分为以下几个步骤:
- 在
CommonKVManager.__init__ 的 prefill 分支中,register_to_bootstrap() 调用之前新增 _sync_bootstrap_port_across_nodes 调用,将本地 bootstrap_port 替换为同步后的端口。
- 新增
_sync_bootstrap_port_across_nodes(local_port) 方法,首先判断是否为多节点 prefill(dist_init_addr 非空且 nnodes > 1),否则直接返回 local_port(单节点恒等)。
- 若为多节点,检查
torch.distributed 是否已初始化,否则抛出 RuntimeError,避免静默退化。
- 通过
get_world_group().broadcast_object(local_port, src=0) 将端口广播到所有节点,并返回同步后的端口。
- 根据 review 建议将
import torch.distributed 从方法内提升到文件顶部,并增加 nnodes == 1 的单节点短路条件。
所有改动仅涉及一个文件 python/sglang/srt/disaggregation/common/conn.py,未引入新的测试文件。
关键文件:
python/sglang/srt/disaggregation/common/conn.py(模块 分离式预填充;类别 source;类型 dependency-wiring;符号 _sync_bootstrap_port_across_nodes, CommonKVManager.init): 该文件是分离式预填充的核心连接管理模块,实现了 bootstrap 端口跨节点同步逻辑,是多节点修复的单一变更点。
关键符号:CommonKVManager._sync_bootstrap_port_across_nodes, CommonKVManager.init
关键源码片段
python/sglang/srt/disaggregation/common/conn.py
该文件是分离式预填充的核心连接管理模块,实现了 bootstrap 端口跨节点同步逻辑,是多节点修复的单一变更点。
以下展示 _sync_bootstrap_port_across_nodes 方法的完整实现,以及 __init__ 中调用它的上下文。代码注释遵循盘古排版规则。
# 在 CommonKVManager.__init__ 的 prefill 分支中(位于 register_to_bootstrap 调用前)
if self.disaggregation_mode == DisaggregationMode.PREFILL:
self.is_dummy_cp_rank = (
not self.enable_all_cp_ranks_for_transfer
and self.attn_cp_size > 1
and self.attn_cp_rank != 0
)
# 同步 bootstrap 端口:在多节点 prefill 中,各节点可能因启动器动态
# 分配而拥有不同的本地端口,需要统一为 leader(rank 0)的端口。
self.bootstrap_port = self._sync_bootstrap_port_across_nodes(
self.bootstrap_port
)
self.register_to_bootstrap()
# 新增的端口同步方法
def _sync_bootstrap_port_across_nodes(self, local_port: int) -> int:
# Broadcast world-rank-0's bootstrap port to all prefill ranks.
# Required for multi-node prefill when the launcher auto-reserves a
# free port per host (e.g. Dynamo's
# `_reserve_disaggregation_bootstrap_port`): without sync, non-leader
# ranks register to `<leader_ip>:<their_local_port>`, hit
# `Connection refused`, and the leader's `prefill_port_table` ends
# up missing rows.
if not self.dist_init_addr or self.server_args.nnodes == 1:
return local_port
if not (dist.is_available() and dist.is_initialized()):
raise RuntimeError(
'torch.distributed must be initialised before '
'CommonKVManager registers to the bootstrap server in '
'multi-node prefill mode.'
)
world_group = get_world_group()
# 广播:src=0 的端口被发送到所有 rank,返回值为广播源的值。
synced_port = world_group.broadcast_object(local_port, src=0)
if synced_port != local_port:
logger.info(
f'Synced disaggregation bootstrap port from leader: '
f'local={local_port} -> leader={synced_port} '
f'(world_rank={world_group.rank_in_group})'
)
return synced_port
评论区精华
风险与影响
- 风险:
- 依赖分布式通信:新方法依赖
torch.distributed.broadcast_object,如果分布式环境未初始化或通信失败,会在启动阶段直接抛 RuntimeError,有助于提前暴露问题,但要求前面的 Scheduler.init_model_worker() 已经完成初始化。
- 单节点无影响:单节点时条件短路,不进行广播,不影响现有单机部署。
- 性能风险极低:仅启动时广播一个整数,benchmark 验证无性能退化。
- 缺少单元测试:PR 未包含直接针对该方法的单元测试,回归风险依赖集成测试覆盖。
- 影响:
- 用户影响:多节点分离式预填充部署不再需要显式指定
--disaggregation-bootstrap-port,默认路径即可正确运行,简化了配置。单节点用户无影响。
- 系统影响:运行时行为无变化,仅增加一次初始化阶段的广播开销。
- 团队影响:减少了因端口不一致导致的部署故障和排查成本,使 sglang 更好的适配 Dynamo 等动态端口分配启动器。
- 风险标记:核心路径变更, 缺少测试覆盖, 依赖分布式通信, 单节点无影响
关联脉络
- PR #25064 [Bug Fix] Add priority property to DecodeRequest to fix AttributeError with --enable-priority-scheduling: 同为分离式预填充模块的 bugfix,修复了解码端属性缺失导致的 AttributeError,与本 PR 的稳定性改进属于同一功能线。
参与讨论