日期:2026-08-14
我们底座上跑着几十个模型实例,既有通用大模型也有几个垂直小模型,白天扛业务流量,晚上做迭代发布。早期每次换权重,要么整体重启实例,要么把流量切到新集群再切回来。重启那几分钟服务全断,切流量又怕新旧两个版本结果不一致,业务方投诉说同一句话上午下午答得不一样。随着模型迭代频率从月级提到周级,这套发布方式已经撑不住,每次发布都像一次小型事故。我们当时判断,必须做到换权重不停机、还能秒级回退,否则迭代越快、事故越多,团队根本不敢发新版本,模型效果反而停滞。
发布流程建在 vLLM 这类推理框架之上,我们给每个模型实例加了权重版本管理。新权重以副本形式加载到显存,加载完成后做小流量灰度,把同一批探针请求同时打给新旧两份权重,比对输出一致性,偏差在阈值内才逐步放量。放量完毕,旧权重副本保留一段时间,一旦放量后监控到效果异常,直接把流量指回旧副本,实现秒级回退。整个过程中实例进程不重启,对外端口不变,业务侧完全无感,发布从原来的人人紧张变成日常操作。
第一个难点是权重热加载期间的显存占用。新副本加载意味着同一张卡上短暂存在两份权重,我们算过,一个七百亿参数模型副本期显存峰值接近平时的两倍,小卡直接会被挤崩。做法是按实例显存余量决定是否允许原地加载,余量不够的先腾退低优实例再加载。第二个难点是新旧权重结果一致性,不能只比是否相同,要算语义相似度和关键字段一致率,我们设了分层阈值,核心字段不一致直接阻断放量。第三个难点是回退的残留,回退后旧副本可能被提前释放,我们改成回退窗口期内副本保活,窗口过了再回收。第四个难点是发布过程可观测,我们给每次发布建了独立看板,灰度比例、一致性偏差、回退次数全在上面,出问题一眼能定位。这里我踩过一次坑:有回回退窗口定太短,放量后第三天才发现长尾效果退化,副本早没了,只能重新发旧版,那次印象很深,之后窗口一律给足。
还有一块是发布节奏的编排,几十个实例不能同时发,我们按业务低峰分批,单批失败不影响其他批,避免一次发布拖垮全局。灰度探针的选取也很关键,要覆盖核心场景而非随机采样,否则一致性偏差会被平均掉,根本看不出来哪里出了问题。
另外,副本的加载时机也有讲究,不能在流量高峰加载,我们排在低峰加灰度,避免副本期显存峰值和业务高峰叠加把实例压垮。还有发布失败的自动回滚,加载副本失败要能自动释放并告警,不能卡在半加载状态,这点我们专门加了健康检查,否则半夜会有人被叫醒。发布这事的细节,全在没人注意的边界情况里。
上线后,模型发布的停机时长从平均约六分钟降到零,发布回退耗时从约十分钟级压缩到约三秒。新旧权重结果一致性偏差率控制在千分之五以内才允许放量,发布失败率从约百分之八降到约百分之一。一个季度内共发布约四十次,其中三次放量后回退,平均回退耗时二点四秒,业务侧未感知到中断。发布看板记录到的灰度平均时长约二十五分钟,比早期切流量方案缩短约七成,运维终于不用熬夜盯发布。
权重热更新最怕显存翻倍把实例挤崩,这步的峰值测算比发布逻辑本身还重要,我们后来把副本期显存预算做成发布前的硬卡点,不够就别原地发,先腾退再加载。一致性格不要只做相等判断,语义层面的偏差才是长尾问题的来源,分层阈值能挡掉大部分坑。回退窗口别抠太紧,长尾退化往往几天后才冒头,副本多保活一天成本有限,换来的是真出事能立刻救。说到底,零重启发布的价值不只是不停机,是让模型迭代敢发、发错能救,团队才敢把频率提上去,模型效果才有持续进步的空间。
我们交过学费的那个长尾退化事件之后,把回退窗口和监控看板都钉死了,现在每次发布先看窗口够不够、看板在不在。零重启发布让人敢发,但敢发的底气来自回退真的能救,这两件事缺一不可,少一个都不敢把频率提上去,模型迭代也会跟着停。
这件事我们磨了快一个季度才顺,回头看,发布系统的可靠性不在框架多先进,在那些没人愿意细想的边界情况有没有被兜住,兜住了团队才敢放手发。
案例片段(已脱敏): 权重副本加载与灰度比对配置:
yaml hot_update: load_mode: in_place_copy # 副本形式加载 vram_guard: true # 显存余量不足则先腾退 canary: probe_qps: 5 consistency: field_eq_rate: 0.995 # 核心字段一致率门槛 semantic_sim: 0.98 rollback_window: 72h # 回退窗口, 副本保活发布日志节选:[2026-08-05 23:10] model=M_lm_v7 -> v7.1 副本加载成功, 显存余量 18GB(够) 灰度探针 300 条, field_eq_rate=0.998 放量 100%, 旧副本保活至 08-08 08-07 监控回退 1 次, 耗时 2.1s