009、负载均衡策略:ECMP、CONGA与全局感知调度
一、从一次线上流量倾斜说起
上个月排查一个线上问题:某AI训练集群里,两台GPU服务器的RDMA流量跑满了,其他机器却闲着。拓扑是标准的Clos架构,照理说流量该均匀分布。抓包发现,同一个训练任务的流,哈希选路总撞到同两条上行链路——经典的ECMP哈希碰撞问题。
这问题让我重新审视负载均衡:在AI集群里,简单的哈希均衡已经不够用了。今天我们就聊聊ECMP的老毛病、CONGA的巧思路,还有全局感知调度的未来感。
二、ECMP:老将的软肋
ECMP(Equal-Cost Multi-Path)是数据中心的老兵,靠五元组哈希做流量分摊。代码里大概长这样:
// 伪代码示意,别直接抄
uint32_t hash = hash_5tuple(packet);
uint32_t index = hash % path_count; // 取模选路
问题就出在这个取模上。AI训练里经常有“大象流”——一条TCP连接就能占满100G链路。哈希模运算可能把好几条大象流挤到同一条路径上,其他路径饿着。更麻烦的是,RDMA流量对丢包和乱序极其敏感,路径拥塞直接拉垮训练效率。
ECMP还有个隐藏坑:路径状态变化时,哈希重分布会导致全量流重新选路,瞬间打乱流量模式。我们吃过亏,某次链路抖动后训练吞吐掉了30%,查了半天才定位到哈希震荡。
三、CONGA:让交换机学会“说话”
CONGA(Congestion-Aware Load Balancing)来自斯坦福和微软的研究,核心思想是把链路拥塞信息通过报文带回来,让发送端动态调整路径。
简单说,它在数据包头上加了个字段记录路径拥塞状态,反向报文把信息带回源端。源交换机维护一张每流每路径的拥塞表,发送时选最不堵的路。代码逻辑大概是这样:
// 收到反向报文,提取拥塞标记
congestion = parse_congestion_tag(reverse_pkt);
flow_table[flow_id][path_id] = congestion; // 更新拥塞状态
// 发送时选路
path = find_least_congested_path(flow_id); // 找最空闲的路径
if (path != current_path) {
reroute_flow(flow_id, path); // 动态切路,注意保序
}
这方案妙在利用了Clos拓扑中双向路径对称的特性,用极小的包头开销(通常几比特)就实现了全局拥塞感知。我们在测试环境压过,大象流场景下比ECMP提升20%以上的吞吐,延迟抖动也小了很多。
不过CONGA对交换机有要求,得支持自定义包头解析和改写——很多商用芯片是闭门的,自己改不动。我们当时用可编程交换机才跑通,这是落地的一道坎。
四、全局感知调度:站在集群视角看流量
CONGA还是局部优化,真正的“大佬”思路是全局感知调度。这不只是网络层的活了,得拉上作业调度器和网络控制器一起干。
比如AI训练的任务分配器,在启动训练任务前,先问问网络控制器:“现在哪条路径空?” 或者更激进点,直接根据网络拓扑规划任务放置——把通信密集的Worker放在同一个Pod里,跨机架的流量能少就少。
我们实验过一种简单策略:训练任务启动时,网络控制器预分配一条专属路径,并做带宽预留。虽然牺牲了一点链路利用率,但训练时间预测性大大提升。代码层面,这得在调度器里加插件:
# 调度器插件伪代码
def allocate_task_with_network(task):
available_racks = network_ctrl.query_available_racks(task.bandwidth_needed) # 问网络控制器
if not available_racks:
return False # 资源不足,等会儿再调度
rack = select_rack(available_racks)
schedule_task_to_rack(task, rack) # 把任务丢到指定机架
network_ctrl.reserve_bandwidth(task, rack) # 预留带宽
return True
这玩法需要SDN控制器、调度器和交换机之间打通API,实施复杂度高,但特别适合大规模长期训练任务。小集群可能不值当,但上万张卡的时候,全局视角的收益就出来了。
五、实战里的几点经验
-
别盲目追新:ECMP在多数场景下够用。先确认你的流量是不是真有大象流、是不是真对乱序敏感,再考虑升级方案。我见过团队折腾三个月上CONGA,结果流量本身就很均匀,白忙活。
-
可观测性是前提:没监控就别玩高级均衡。交换机端口计数、流级遥测(INT)、端到端吞吐延迟,这些数据齐了再动手调。我们当初靠sFlow采样抓到哈希碰撞,没这个证据根本不敢动线上网络。
-
保序是关键:动态调路可能引发乱序,TCP还好,RDMA/ROCE直接崩。CONGA这类方案通常只在连接建立时或长时间空闲后切路,就是怕乱序。自己实现的话,一定要加序列号检查或者切路前清空队列。
-
测试环境要带损:实验室里万物完美,一上线就崩。一定要在测试环境注入丢包、延迟、抖动,看均衡策略是否健壮。我们模拟过链路故障切换,发现某个CONGA实现会疯狂震荡,后来加了阻尼系数才稳住。
六、写在最后
负载均衡没有银弹。ECMP简单可靠,CONGA精巧灵敏,全局调度宏大全面。选哪个,看你的集群规模、流量特性和运维能力。
我的习惯是:小集群用ECMP调好哈希种子就行;中等规模上CONGA类方案,重点解决大象流问题;超大规模且业务可控,再考虑全局调度。另外,硬件能力往往决定方案上限——先看清楚交换芯片支持什么,再画架构图。
流量均衡是个持续调优的过程,每次业务迭代都可能打破平衡。保持监控,保持谨慎,多留几个手动开关。哪天半夜被叫醒处理流量倾斜时,你会感谢这个习惯的。
下期预告:聊了均衡,下次我们看另一个头疼问题——拥塞控制。AI集群里的QCN、DCQCN、HPCC,到底怎么选?
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)