跳到主要内容

52 篇博文 含有标签「sre」

查看所有标签

你的 Agent 链路中无人分配的延迟预算

· 阅读需 11 分钟
Tian Pan
Software Engineer

你的 Agent 有一个延迟 SLO。有人把它写在了文档里:“响应时间低于 8 秒,p95”。但没人决定这 8 秒该如何分配。检索调用没有细分预算,规划步骤没有细分预算,模型因为感到不确定而决定调用的第三个工具也没有细分预算。预算在边界处只是一个数字,而在内部则完全不存在。因此,当一个五跳链路冲破 8 秒时,值班工程师盯着追踪链路(trace),却无法回答那个唯一重要的问题:到底是哪一跳超时了?

这就是拥有“延迟预算”的服务与拥有“延迟愿望”的服务之间的区别。预算是分配给每个组件并强制执行的;而愿望是在出口处测量并祈祷达标的。大多数 Agent 系统发布时都带着愿望,因为跳数结构是动态的——模型决定调用多少次工具——而且为无法控制的事情制定预算感觉是不可能的。事实并非如此。正因为你无法控制它,你才更需要为它制定预算。

Agent 的演练日:排演那些无法复现的故障

· 阅读需 11 分钟
Tian Pan
Software Engineer

传统的混沌工程建立在一个默认的假设之上:如果你两次注入同样的故障,你会得到两次同样的失败。停掉 pod,观察故障转移,修复漏洞,再次停掉 pod 以进行确认。整个学科——假设、爆炸半径、稳态指标——都假定系统具有足够的确定性,使得实验是可重复的。

智能体系统从根本上打破了这一假设。在智能体运行过程中注入工具超时,模型会重新规划路径——有时它会重试,有时它会换一个工具,还有时它会自信地编造一个从未获取到的结果。针对相同的提示词运行相同的故障,你最终会得到不同的轨迹,因为故障路径是通过一个随机规划器(stochastic planner)运行的。上周二你在生产环境中看到的故障永远不会以完全相同的形式再次发生。而这恰恰就是你必须对其进行演练的原因。

让 Agent 先接警:AI 故障响应的信任阶梯

· 阅读需 10 分钟
Tian Pan
Software Engineer

几乎每起事故的前 15 分钟都是机械式的。拉取每个人都会拉取的那四张图表。对比事故开始时的部署差异。检查今天翻转了哪些功能标志(feature flags)。在运行手册(runbook)维基中搜索错误字符串。这些都不需要判断力——它只需要你保持清醒,而在凌晨 3 点,你的值班工程师正把这些时间花在找笔记本电脑、加入语音会议(bridge),以及回忆哪个仪表盘才是真正有用的那个。在人类解锁屏幕之前,智能体(agent)就可以完成这一切。

然而在大多数组织中,关于 AI 在事故响应中应用的讨论往往止于一个段子:“我们听说有个团队的自动修复脚本搞垮了生产环境。”于是,整个想法就被禁绝了——不是限制范围,不是分阶段实施,而是直接禁绝。这是一个范畴错误。那些恐怖故事讲的是自主权阶梯的最顶层,而团队的反应却是拒绝踏上最底层。在最底层,智能体没有任何写入权限,它能做的最坏的事情也就是在 Slack 里发了一段错误的话。

思维的 p99:当模型决定你的请求耗时多久

· 阅读需 12 分钟
Tian Pan
Software Engineer

你拥有的每一份延迟优化手册(latency playbook)都是为那些单次请求工作量大致恒定的系统编写的。数据库查询耗时相对固定。图像缩放随像素数变化,而这是预先可知的。甚至经典的 LLM 补全也有可预测的成本范畴:输入多少 token,输出有限的 token。推理模型悄无声息地打破了这一假设。当模型在运行时自行决定思考多久——且它是基于问题难度来决定时——响应时间便不再是基础设施的属性,而变成了问题本身的属性。

后果首先体现在你的分位数指标上。在生产环境中运行推理模型的团队报告称,p99 延迟会激增到 p50 的三到五倍,这不是因为主机变慢或缓存失效,而是因为百分之一的请求恰好真的很难。你的自动扩缩容策略、超时策略和 SLO 仪表板都是针对一个“这种差异意味着系统出现故障”的世界而调整的。而现在,这却意味着系统正按设计运行——你用来管理尾部延迟的所有工具都指向了错误的原因。

理解债:没人能看懂的凌晨两点系统

· 阅读需 10 分钟
Tian Pan
Software Engineer

传呼机在凌晨 2:14 响起。结账服务正抛出 500 错误,收入在流失,而你是值班工程师。你调出故障模块并开始阅读。代码很整洁——函数命名规范,结构合理,甚至还有几处有用的注释。然而你完全不知道它是干什么的。代码不是你写的。你团队里的任何人都没真正写过它。四个月前,一个智能体(agent)生成了这段代码,它通过了评审,测试通过了,并从此在生产环境中运行。现在它出故障了,而那个理应修复它的人却是第一次见到它。

这就是理解债(comprehension debt):你的组织运行的代码量与人类实际理解的代码量之间日益扩大的差距。它不会显示在仪表盘上。当一切看起来都健康时,它在默默累积,并在最糟糕的时刻——在事故期间,当你对自己系统的理解不足其代价是以停机时间来衡量时——到期偿还。

那些被静音的 LLM 报警:当每一次值班看起来都和上一个一模一样

· 阅读需 11 分钟
Tian Pan
Software Engineer

一次真实的回归在生产环境中持续了两天。告警(Page)已经触发了。它触发得完全正确,阈值准确,严重程度也恰当。三周前,值班轮值(On-call rotation)为该告警族添加了一条静默规则,因为该系列中的每一条告警到目前为止都以同样的注释结案:“无须操作,调查中”。复盘(Post-mortem)无法诚实地将这种静默行为称为错误。这是对一系列值班人员没有 Playbook(运行手册)可循的告警流所做出的理性适应。那个重要的回归就在一个被静默的频道中发布了,因为团队的监控栈产生的信号无法指导具体行动,而团队唯一的应对方式就是:停止倾听。

这并不是一个告警 Bug。这是当团队沿用旧有的 Playbook 对 AI 功能进行埋点时,产生的一种结构性特征。延迟、错误率、拒绝率、输出 Schema 符合度、Judge-eval 漂移——每一个都是合理的指标。每一个触发时都带有同样模糊的“模型行为改变”措辞。但它们都没有告诉值班工程师该做什么,因为没有人写过将每个信号映射到具体动作的 Runbook,因为大多数情况下,信号并不能对应到具体的动作。值班轮值吸收着噪音,直到噪音盖过了信号,然后值班人员就会绕过产生这些信号的频道。

重试预算如何从你的仪表板中隐藏了供应商的真实错误率

· 阅读需 12 分钟
Tian Pan
Software Engineer

周会汇报的幻灯片上写着 99.9%。发票则显示账单翻了三倍。这两个数字在相邻的仪表盘上共存了数月,却没人发现它们衡量的是不同的世界。可靠性数值是重试后的结果——每一个最终返回 200 的调用都被计为成功——而成本数值则是客户端进行的每一次尝试,按 Token 计费。在两者之间,是一个慷慨的五次重试循环,以及一个尾部延迟正在悄悄恶化的供应商。第一次有人同时观察这两个数字是在一次故障期间,当时成本异常告警在可用性告警之前就触发了。

这就是整个模式。一个看起来像是可靠性机制的重试预算,本质上也是一个成本-质量调节旋钮,而那些只关注其中一面的团队,正在为一个发票最终会修正的可用性数字买单。

你的故障指挥官无法执行的智能体运行手册

· 阅读需 10 分钟
Tian Pan
Software Engineer

报警在当地时间 02:17 响起。值班 SRE 在手机上打开智能体运行手册,阅读第一步:“检查智能体的工具调用追踪,寻找异常的工具使用情况。”他们打开链接,却遇到了一个他不属于的工作区的 SSO 登录提示。第二步说要检查提示词构建日志;同样碰壁。第三步说回滚到上一个提示词版本,但部署权限被限制在了一个他不在的团队中。等他弄清楚该向哪个 Slack 频道上报,并叫醒 AI 团队的产品经理时(因为她是 02:17 唯一能找到的人),九十分钟已经过去了,而客户可见的回归故障仍在持续给出错误答案。

事后分析会将权限鸿沟确定为直接原因。而更深层的不适感在于,这份运行手册在白天读起来很顺畅,但在深夜执行时却被封锁,因为编写手册的人拥有执行者所不具备的权限。

你的智能体平台忘了配置的值班轮换

· 阅读需 12 分钟
Tian Pan
Software Engineer

AI 平台团队有四名工程师。他们七个月前发布的内部 Agent 现在每天为 200 名员工回答问题。在第一个月,创始工程师亲自处理了每一个 Slack 消息——周二晚上 11 点,周日上午,甚至公司团建的晚上。随后,她因推动采用率方面的贡献而晋升为资深工程师(Staff Engineer),三周后,她在下午 6 点后就不再查看频道了,因为那是资深工程师该做的。原本打算取代她的值班轮换(on-call rotation)从未正式化,因为运营模式总是打算在“试点之后”再解决。

当 Agent 针对四分之一的用户静默降级的那天——一个悄然落后的检索索引,或者改变了拒绝行为的模型版本切换,或者是架构轮换后现在返回空数组的工具——投诉并不会降临到平台团队的传呼机(pager)上。它们落在帮助台队列中,由那些无法访问 Agent 追踪(traces)、不知道什么是系统提示词(system prompt)、并且被 IT 部门告知该 Agent “由 AI 团队负责”的人员处理。从第一个用户投诉到第一位工程师查看 trace,中间过去了 16 个小时。平台团队没有人玩忽职守;只是根本就没有人在执勤。

供应商配额在你的全球流量从未选中的时区重置

· 阅读需 10 分钟
Tian Pan
Software Engineer

你的每月 Token 配额在 00:00 UTC 重置。你最大的客户在东京,他们在 21:00 UTC(即当地时间第二天早上 6:00)达到峰值负载。当重置时刻到来时,东京的工作日已经在配额耗尽的降级方案中消耗了该周期的最后六个小时。429 错误看起来只是“偶发”,因为你仪表板上的 UTC 日历轴将每日重置边界隐藏在了普通的时间戳之中。

这不是速率限制(rate limit)的 Bug。这是一个日历 Bug。供应商为了结算方便选择了一个重置时钟,而你流量的地理分布决定了哪些客户会分配到周期末尾的空窗期。那些将配额定价为统一资源的团队,正基于一个用户从未见过的日历来进行配额分配。

你的仪表盘以三种不同方式统计了那次重试

· 阅读需 13 分钟
Tian Pan
Software Engineer

一个 Agent 运行了。计划步骤(plan-step)崩溃了。工具调用(tool-call)步骤在经历了两次 500 错误重试后,在第四次尝试时成功了。用户得到了他们的答案。

那算是多少个事件?问产品,这是一个事件 —— 用户得到了有效结果,因此转化漏斗统计了一次转化。问 SRE,那是三个失败加上一个成功,底层步骤的错误率是 75%。问财务,那是四次计费推理,两次重试的工具调用,以及大约四倍于产品部门预测的单位成本。每个团队的仪表盘都是正确的。但它们也是不可调和的,一旦有人试图调和它们 —— 通常是在事故回顾期间 —— 他们会发现团队已经基于三个相互矛盾的可信度图景运行了数月之久。

你的后端基础设施并非为流式响应而设计

· 阅读需 13 分钟
Tian Pan
Software Engineer

流式传输(Streaming)是一项产品决策。设计团队的某个人看到竞争对手的聊天 UI 像打字机一样逐个吐出 Token,看到用户在第 200 毫秒看到第一个字符出现时肩膀放松了下来,而不是盯着 4 秒钟的空白屏幕发呆,于是决策就此达成:我们要做流式传输。这个拉取请求(PR)修改了 API 网关中的三个文件。现在,模型输出通过服务器发送事件(Server-Sent Events,SSE)增量刷新。功能在周二上线,周三的满意度评分就有了明显的提升。没人向基础设施团队提工单。

一个月后,值班工程师盯着三个互不一致的仪表盘发愁。自动扩缩容(Autoscaler)配置的 Pod 数量是 CPU 图表显示需求量的两倍。P99 延迟仪表盘坏了——不是出了故障,而是变得无法解读,因为直方图分桶(Histogram Buckets)止步于 5 秒,而现在大多数 Span 都落在溢出区间。上一季度定价时的容量模型显示,该服务每节点每秒可处理 1200 个请求。而值班人员面前的图表显示,它在处理 400 个请求时就已经难以为继。