日期:2026-08-22
我们一张推理卡半夜突然掉线,上面正跑着的半批请求直接全挂。上游调用方见超时就开始重试,重试流量又砸到剩下那几张卡上,负载瞬间翻倍,第二张卡也被拖垮,连锁雪崩。那天凌晨被叫起来救火,手动摘节点、拉备用、迁流量,折腾到天亮,丢了一批请求,业务方一早追着问。这种单点故障放大成全集群不可用的事,在我们规模上去之后迟早会来,靠人肉值班顶不住。
根因有两层:一是故障探测慢,等我们收到告警卡已经掉了一阵;二是没有在途请求迁移机制,节点一死上面跑的全废,只能靠上游重试兜底,而重试恰恰是雪崩的推手。
我们给推理集群加了健康探测和自愈链路。每个节点定期上报心跳,探测覆盖网络连通、GPU 显存健康、推理端口响应三个维度,任一异常立即标记为不可用。网关侧的路由表实时同步节点状态,新请求不再往坏节点发。
对于节点下线时已接收但尚未返回的在途请求,我们做了迁移:网关记录请求归属节点,节点异常时把在途请求重新投递到健康节点重算,调用方无感知。备用节点平时处于温状态(模型已加载、权预热),探测到容量缺口时自动拉起补位。故障恢复后流量按健康度逐步重平衡,避免恢复瞬间又打满。
故障快速探测和误判是一对错。探测太灵敏,一次网络抖动就摘节点,反而制造人为故障;太迟钝又来不及止损。我们设了连续三次异常才摘流,并对探测本身做独立通道,避免探测和被探测共用一条坏链路互相误报。
在途请求迁移是难点。重算意味着重复消耗算力,而且有状态请求(如流式生成已输出一半)没法无缝续上。我们的取舍是:非流式请求直接重投健康节点;流式请求因难续,改为快速失败并让上游短退避,配合降低重试并发避免雪崩。这个取舍我后来觉得是合理的,追求绝对无损反而把系统复杂度推上天。
备用节点冷启是个坑。最初备用节点是冷备,真要补位时加载模型要好几分钟,切换窗口里又掉了批请求。改成温备后,补位时间从分钟级降到秒级,雪崩概率大幅下降。
流量重平衡容易被忽略。故障恢复后如果瞬间把所有流量切回,刚恢复的节点会被打爆,二次故障。我们按健康度逐步放量,先放两成观察,没问题再提,给节点热身的时间。这个节奏是踩过坑才有的,有一次恢复后全量回切,节点直接又被压垮,等于白救。另外在途请求重投要做幂等保护,同一请求别因为迁移被算两次,我们一开始没加,出现过重复计费的客诉,虽少但很尴尬,后来在网关层加了去重。
演练我们也补上了。光有自愈链路不够,得定期演一遍真故障,验证探测、摘流、迁移、补位全链路真的通。我们每月挑一张卡做模拟掉线,看切换时长是否还在预期内、有没有新冒出来的依赖漏网。有次演练暴露出备用节点温备脚本偶发没拉起,幸亏在演练里发现,没等到真实半夜。自愈能力不练会生锈,这是真体会。
故障根因我们也顺手收集。每次自愈触发后,系统记一笔为什么挂的,是显存 ECC、是网络闪断还是负载突增,月度汇总给硬件和容量团队。这把被动救火变成了主动换盘换网,我们靠这个把同因故障从反复发生压到基本绝迹。
案例片段(已脱敏): 某节点 GPU 显存 ECC 报错,心跳连续三次失败,12 秒内被标记为不可用,网关同步摘流。该节点上 37 个在途非流式请求中 29 个被重投健康节点成功返回,8 个流式请求快速失败并由上游在 200ms 后退避重试。备用温节点 8 秒完成补位,集群吞吐 40 秒内恢复。全程无人工介入,业务侧仅 8 个流式请求出现一次短暂重连。
故障切换时长(从异常到摘流并补位)从原来人工平均约 25 分钟降到约 40 秒。请求成功率在故障场景下从约 82% 提升到约 99%。雪崩次数(单点故障演变为多节点不可用)从季度内 3 次降到 0。人工介入次数大幅下降,值班同学终于能睡整觉。
我们复盘时把"温备"列为性价比最高的一笔投入,比起堆更多冗余卡,常备少量热节点更省钱也更稳。
单卡掉线绝不能拖垮全集群,这是推理服务上规模后的第一课。健康探测要快但别过敏,连续异常才摘流,探测通道要独立,否则自己制造故障。在途请求能迁则迁,流式这种难续的干脆快速失败配退避,别为了无损把复杂度搞到失控,我们追求过一阵绝对无损,后来主动放弃了。备用节点务必温备,冷启那几分钟足够再掉一批请求,这是我们交过真金白银学费换来的。自愈链路建好后,值班从救火变成偶发确认,团队松了口气。