跳到主要内容

备用方案变成了默认方案:为什么你的分层配比需要 SLO

· 阅读需 12 分钟
Tian Pan
Software Engineer

仪表盘显示 0.5% 的请求触发了回退(fallback)。仪表盘这么显示已经持续六个月了。直到有人从头重新运行遥测数据(telemetry),发现次级模型正承载着 38% 的流量,而预设回复(canned-response)层级则处理了另外 9% 的流量。团队在路线图评审中一直讨论的尖端模型“主路径”,实际上已沦为少数派体验。没有人注意到这一点,因为没有任何警报被触发 —— 每次降级都是一个小规模的、理由充分的、局部正确的决定,而累积的偏差从未超过任何人事先设定的阈值。

这就是我想要定义的失效模式:成了默认项的回退机制。这不是故障,也不是单个组件的回归。它是产品表面的缓慢轮转,退而求其次的路径不再是安全网,而成了核心体验。团队的心理模型与生产现实渐行渐远,而这种差距是隐形的,因为现有的度量指标(meters)旨在检测失败,而非检测组合(mix)。

我要提出一个更强有力的观点:如果你的 AI 功能拥有两个以上的服务层级,那么你的层级组合(tier mix)本身就是一个 SLO。如果你没有测量它,你其实并不知道你发布了什么。

默认路径是如何悄悄偏移的

这种机制很少源于单一的错误决策。它是一系列局部合理的决策序列,每一项都有文档记录,每一项都有节省成本或提高可靠性的理据,每一项都在某种程度的批准后上线。每一项决策都在路由层留下了永久的降级,而没人再去重新评估。

一个典型的演变过程:

  • 上线了一个“智能路由器”。它根据“能省则省”的原则,将复杂度得分低于某个值的提示词降级到更便宜的次级模型。发布初期为了“安全起见”限制在 5%,随后在值班人员忙于处理无关事故的一周内增加到了 50%,之后便再未调整,因为成本仪表盘看起来非常漂亮。
  • 三月的一次事故中触发了熔断器(circuit breaker)。那次事故是真实存在的,熔断器也尽了职责。事故后的修复解决了底层问题,但从未重新激活(re-arm)熔断器,因为一旦仪表盘变绿,熔断器就不再报警,也没人负责那个半开状态的探针。
  • 添加了 Token 支出成本监控,当每日支出超过阈值时,自动切换到预设回复。该阈值已连续 60 天被触碰。警报最初很吵,所以有人将其路由到了低优先级频道,现在它在无人阅读的情况下被刷走。
  • 在一次容量危机中,响应缓存从“建议使用”提升为“首选”。危机结束了,但这种优先级提升却保留了下来。

这些都是变成了常态的特性标志(feature flag)。过时的标志在变得不必要的那天不会发出刺耳的失败声;它们让两个现实同时并存 —— 你认为的当前路径,以及软件实际执行的路径。Knight Capital 曾在 45 分钟内损失 4.6 亿美元,那起事故就是由于重新激活了一个控制过时代码路径的标志。AI 回退机制具有相同的形态,只是后果更隐蔽:用户得到的是较差的答案,而不是错误的交易。

为什么延迟和错误率 SLO 无法捕获它

即便是一个做好了 SRE 基础工作的团队仍然会漏掉这一点。原因很简单:所有标准 SLO 都是针对“单次请求”的度量。次级模型的 p95 延迟可能优于主模型。预设回复的错误率从定义上讲就是零。如果你用预设回复处理每一个请求,你的错误率 SLO 将处于有史以来最健康的状态。度量指标对真正关键的问题视而不见:我们是从哪个层级提供服务的?

AI 工作负载的标准可观测性清单 —— Token 吞吐量、延迟、错误率、重试次数、回退触发 —— 只能发出检测“事件”(event)的信号,而不能检测“组合”(mix)。回退触发率是最接近的指标,但大多数团队将其测量为“这次请求是否回退了”,而不是“产品预期交付路径服务了多少比例的请求”。这是两个不同的问题,而后者才是用户评价你的标准。

这是一种需要抛弃旧习的重新思考。SRE 接受的训练是针对阈值违规报警:延迟超过 X,错误率超过 Y。层级组合不是违规,而是滑动。主层级份额每周 1% 的漂移对于任何传统警报都是不可见的,但在一个季度后却是灾难性的。你需要一个专门用于察觉缓慢变动的度量指标。

将层级组合作为一等公民 SLO

解决方法是将层级组合视为与延迟和错误率同等地位的服务水平目标(SLO)。具体来说:

  • 定义主层级份额目标。 “在 7 天滚动窗口内,97% 的请求由主层级服务”是一个非常好的 SLO。选择与你的产品定位相匹配的数字;如果团队一直告诉客户“由尖端模型驱动”,那么 97% 都是慷慨的。如果产品的叙事是“跨层级的智能路由”,这个数字可能会低一些,但它必须存在且必须被捍卫。
  • 针对份额的燃烧率(burn-rate)报警,而不仅仅是针对事件。 借用延迟 SLO 中的多窗口燃烧率报警模式。数周内的缓慢漂移应该像数小时内的快速下降一样触发报警。重点是捕获任何单一事件都无法体现的轮转。
  • 将层级组合随时间的变化绘制为堆叠面积图,而非数字。 堆叠面积图是能够体现漂移的可视化方式;单一的百分比会掩盖它。在季度回顾中,看到六个月前绿带缩小的图表,其价值超过十个报告“回退率:正常”的仪表盘。

这种方法之所以奏效,是因为它反转了失效模式。目前的默认状态是“除非看起来坏了,否则不触发事件”,而这里的“坏了”恰恰在于“一切看起来都正常”。组合份额度量指标旨在稳态本身发生偏移时触发。它正是你需要的度量指标,因为这种失效没有突发的峰值。

保持混合比例真实的三项准则

定义 SLO 是必要的,但还不够。三项操作准则必须与之配套。

每条降级路径从诞生起就伴随着指标和默认开启的告警。 这是一个文化规则,而非工具规则。当工程师添加一个新的降级开关时,发布清单要求必须具备“我们正从该层级提供多少比例的流量”的测量指标,以及团队承诺的阈值告警。没有这两项,任何新的降级方案都不能发布。这听起来很官僚;但在实践中,每次发布只需花费十分钟,却能省去事故后询问“这东西是从什么时候开始承载这么多流量的?”这种考古式的溯源工作。

定期对每个降级开关进行“重新校准”演练。 借鉴混沌工程的实践:每个季度,团队都会梳理每一个熔断器、成本防护、复杂度路由和缓存提升杠杆。针对每一项,都要对两个问题给出“是/否”的回答 —— 这一项是否仍有必要?它的触发条件是否依然经过校准?任何回答为“我不知道”的项都会变成一张待办工单。目的不是为了移除降级方案,而是为了重置“它们是临时状态”这一假设。如果不进行这项演练,过去两年中使用的每一个紧急杠杆都将处于永久开启状态。

设立“混合比例负责人”这一明确角色。 每个添加降级方案的团队都对其添加的部分负责,但没有人对 混合比例 负责。这就是导致偏离发生的组织失效。混合比例是一个横向的产品界面,必须有人 —— 通常是值班负责人或平台团队 —— 被明确任命为“平均用户实际得到了哪个层级的服务?”这一问题的负责人。他们在季度评估中的工作就是捍卫这个图表。

成本与信任视角

当关于 SLO 的对话遭到领导层抵制时,两个视角会很有帮助。

成本视角非常直接:当 38% 的流量被静默路由到次级层级时,团队既在为主要层级的预留容量买单,又在提供次级层级的质量。这是两头落空 —— 预留的容量没有惠及用户,而用户获得的质量与团队付出的成本并不匹配。在季度业务复盘中以金钱为单位指出这一点,往往比任何可靠性论证都能更快地推动 SLO 的落地。

信任视角更难但也更重要。用户连续两个月收到预设响应,从而得出结论:这个功能坏了。他们并没有错;他们正在衡量团队没有衡量出的东西。他们的内心计数器是“这个产品是否帮到了我”,如果预设响应运行的时间足够长,那个计数器就会进入用户流失的领域,他们会告诉同事这个功能很糟糕。团队的仪表盘显示可用率是 99.95%。这两个数字都是真实的。但用户的数字才是决定产品能否生存的关键。

降级路径是产品的一个界面

解决这一问题的架构认知是:降级路径不是基础设施,它是产品的一个界面。你降级体系中的每一个层级都是你产品的一个版本,服务于一部分用户,而这些层级的 混合比例 才是你交付的真实产品。如果团队精心地设计了主要路径,而将次级路径视为“作为降级方案已经足够好”,那么随着时间的推移,次级路径就会在无意识中变成用户的核心体验。

这会产生两个后果。

第一,次级层级值得进行专门的质量优化。如果 38% 的流量将落到那里,那么“一个放在开关后的普通的 7B 模型”就不再是一个可以接受的答案。拥有主要路径的团队应该像对待产品规范一样对待主要和次级路径之间的“断层” —— 具体哪些地方降级了,用户如何被告知(或不被告知),答案与主要路径相比是什么样的。目前这个断层往往只是一个理想化的“有用性略有下降”,但在实践中,它是用户能感知到的阶跃式变化。

第二,预设响应层需要一次诚实的审计。大多数预设响应层是为 0.5% 的极端情况编写的,而且痕迹明显。它们言语生硬,拒绝回答实际问题,变着法儿说“我现在遇到了麻烦”。对于 0.5% 的情况,这些答案没问题。但对于 9% 的情况,它们就是一种负担,因为同一个用户会不断遇到它们,并得出功能无法使用的结论。要么投资于预设层级的质量,要么投资于减少从该层级提供的流量。在它服务了近十分之一流量的情况下仍坚称该层级是“罕见”的,这只是一种姿态,而非工程决策。

本周要做的事情

如果这篇文章描述了你的系统而你尚未察觉,有三件具体的事情可以快速产生信号。

针对你路由层的日志运行一个过去 30 天的单次查询,报告按服务层级分组的请求计数。将其绘制成以天为 X 轴的堆积面积图。这个图表要么是平的(说明你没问题),要么是有坡度的(说明你有故事要讲)。查询只需一个下午;而图表将重新组织你下一个冲刺周期的工作。

列出系统中的每一个降级开关 —— 每一个熔断器、成本防护、复杂度路由、响应缓存提升、降级模型选择器。针对每一项,写下谁负责它、它上次改变状态是什么时候、以及它的触发条件是什么。其中一半可能都没有负责人。这个清单就是你的重新校准待办事项。

选择一个主要层级占比的目标数字 —— 95%、97%,或者任何能捍卫你产品叙事逻辑的数字 —— 并在本季度将其写入团队的 SLO 文档中。让它像延迟指标一样关键。数字可能会定错,这没关系。做出承诺这个动作本身,就会产生去衡量并捍卫它的压力。

变成默认路径的降级方案并不是单个组件的 Bug。它是没有人为稳态负责时的必然结果。那个为层级混合比例添加 SLO、指定负责人并定期重新校准降级开关的团队,正在选择大多数用户所看到的。不这样做的团队其实也在做选择 —— 他们只是在让选择由未被审查的决策堆积而成,并在几个月后发现,他们交付的产品与他们认为自己交付的产品,完全是两回事。

References:Let's stay in touch and Follow me for more thoughts and updates