执行摘要
- 一句话:修复 DP attention 路径端口溢出当基础端口接近 65535
- 推荐动作:该 PR 修复了实际用户报告的启动崩溃问题,设计上兼顾了多节点确定性要求,且对非溢出场景零影响。建议合并,并考虑后续为端口分配逻辑补充单元测试。
功能与动机
Issue #20257 报告了在 SLURM 环境下使用 --enable-dp-attention 且 master 端口接近 65535 时,派生端口(如 65536)非法导致 AttributeError: 'NoneType' object has no attribute 'pid'。PR body 指出这是 PR #2826 对非 DP 路径修复的跟进,但 DP attention 路径仍使用 TCP 端口算术偏移且无边界检查。
实现拆解
python/sglang/srt/utils/network.py:增加 MAX_VALID_PORT 常量(65535),在 wait_port_available() 入口对端口范围进行前置校验,非法端口直接抛出 ValueError;将 error_message 初始化为兜底字符串避免 UnboundLocalError;修复 find_process_using_port() 返回 None 时仍访问 process.pid 的 bug,将相关逻辑移入 else 分支。
python/sglang/srt/server_args.py – 单节点 DP:将 server_args.port + ZMQ_TCP_PORT_DELTA 的计算改为先计算 derived_port,若超过 65535 则改用 server_args.port - ZMQ_TCP_PORT_DELTA,保证派生端口合法。
python/sglang/srt/server_args.py – 多节点 DP:定义 NUM_DERIVED_PORTS = 5,检查 dist_init_port + NUM_DERIVED_PORTS > 65535,若超限则将 port_base 设为 dist_init_port - NUM_DERIVED_PORTS - 1,否则沿用递增逻辑。推导公式保证所有节点无通信即可得出一致端口。
关键文件:
python/sglang/srt/utils/network.py(模块 网络工具;类别 source;类型 core-logic;符号 MAX_VALID_PORT, wait_port_available): 实现了端口范围校验和异常处理修复,是防御性编程的核心文件。
python/sglang/srt/server_args.py(模块 服务参数;类别 source;类型 core-logic;符号 init_new): DP attention 端口派生逻辑所在,包含单节点和多节点的溢出规避核心变更。
关键符号:wait_port_available, PortArgs.init_new
关键源码片段
python/sglang/srt/utils/network.py
实现了端口范围校验和异常处理修复,是防御性编程的核心文件。
# python/sglang/srt/utils/network.py
MAX_VALID_PORT = 65535 # TCP 端口上限
def wait_port_available(
port: int, port_name: str, timeout_s: int = 30, raise_exception: bool = True
) -> bool:
# 前置校验:拒绝非法端口,给出清晰错误而非后续的 None 属性异常
if port < 0 or port > MAX_VALID_PORT:
raise ValueError(
f"{port_name} has invalid port number {port}. "
f"Valid TCP port range is 0-{MAX_VALID_PORT}."
)
# 提前初始化兜底消息,避免超时未进入 logging 分支时 UnboundLocalError
error_message = f"{port_name} at {port} is not available"
for i in range(timeout_s):
if is_port_available(port):
return True
if i > 10 and i % 5 == 0:
process = find_process_using_port(port)
if process is None:
logger.warning(
f"The port {port} is in use, but we could not find "
f"the process that uses it."
)
else:
# 原 bug:process 为 None 时仍执行此分支,引发 AttributeError
pid = process.pid
error_message = (
f"{port_name} is used by a process already. "
f"{process.name()=}' {process.cmdline()=} "
f"{process.status()=} {pid=}"
)
logger.info(
f"port {port} is in use. Waiting for {i} seconds "
f"for {port_name} to be available. {error_message}"
)
time.sleep(0.1)
if raise_exception:
raise ValueError(
f"{port_name} at {port} is not available in {timeout_s} seconds. "
f"{error_message}"
)
return False
python/sglang/srt/server_args.py
DP attention 端口派生逻辑所在,包含单节点和多节点的溢出规避核心变更。
# python/sglang/srt/server_args.py (PortArgs.init_new 方法中 DP 分支 )
else:
# DP attention. 使用 TCP 端口以支持单节点与多节点
if server_args.nnodes == 1 and server_args.dist_init_addr is None:
# 单节点:基于 server_args.port 派生
derived_port = server_args.port + ZMQ_TCP_PORT_DELTA
if derived_port > 65535:
# 与 PR #2826 相同的递减策略,避免端口溢出
derived_port = server_args.port - ZMQ_TCP_PORT_DELTA
na = NetworkAddress("127.0.0.1", derived_port)
else:
na = NetworkAddress.parse(server_args.dist_init_addr)
dist_init_host = na.host
dist_init_port = na.port
# 需要连续 5 个端口:port_base, detokenizer, rpc, metrics, scheduler
# 多节点下必须确定性推导(不可搜索可用端口)
NUM_DERIVED_PORTS = 5
if dist_init_port + NUM_DERIVED_PORTS > 65535:
# 超限则递减,确保所有派生端口 ≤ 65535
port_base = dist_init_port - NUM_DERIVED_PORTS - 1
else:
port_base = dist_init_port + 1
detokenizer_port = port_base + 1
rpc_port = port_base + 2
metrics_port = port_base + 3
load_collector_port = port_base + 5
# ... 其余端口赋值及 wait_port_available 调用不变
评论区精华
风险与影响
- 风险:
- 端口冲突风险:递减策略可能导致派生端口与系统预留端口(如 0-1023)重叠,但
dist_init_port 通常为高位端口(如 SLURM 分配),冲突概率低。
- 缺少测试覆盖:未增加单元测试验证端口溢出路径,回归风险虽低但存在。
- 单节点递减假设:单节点 DP 中假设
server_args.port - ZMQ_TCP_PORT_DELTA 仍为正数,若 server_args.port 接近 0 可能下溢,但实际场景中用户端口通常较大。
- 影响:
- 用户:使用 DP attention 且基础端口接近 65535(常见于 SLURM 环境)的用户将不再启动崩溃。
- 系统:端口分配逻辑变更仅影响启动阶段,不影响推理性能。
- 团队:变更集中在两个源文件共 33 行增量,影响面小。
- 风险标记:缺少测试覆盖, 启动流程变更
关联脉络
- PR #2826 Fix port overflow in non-DP path: 该 PR 是 #2826 对非 DP 路径修复的跟进,使用了类似的递减策略。
- PR #21567 Changes to DP attention ZMQ networking: Review 中 alexnails 提及此 PR 修改了 DP attention 的 ZMQ 网络行为,与本 PR 有重叠范围。
参与讨论