Cloud Run多智能体状态共享陷阱:演示通过不等于架构正确

原文:https://dev.to/dannwaneri/my-cloud-run-multi-agent-fleet-passed-its-demo-the-architecture-was-still-wrong-1p (作者 @dannwaneri)

关联告警触发了。三个站点,相同异常类型,在时间窗口内。编排器成功捕获并实时记录了这次针对已部署服务的告警。干净利落,一次通过。

然后我问了一个差点没问的问题,因为系统刚刚明明运行成功了:它为什么成功了?

答案不是“因为逻辑正确”,而是“因为 Cloud Run 碰巧把两个请求路由到了同一个运行实例上”。好家伙。

我的编排器用一个普通的 Python 列表在进程内存中保存最近的风险事件列表。本地测试时能用,因为只有一个进程。在线上也能用,是因为 Cloud Run 在低流量下通常会复用同一个实例,而不是启动第二个。这两者都不是保证。一旦流量模式变化,两次读取落在不同实例上,第二个实例将完全不知道第一个实例的存在。本应触发的关联告警就会静默地不触发。

一个能通过自己演示的 Bug 是最难发现的。因为根本没有错误可追踪。只有一个绿色的对勾。

我在构建什么

VES Fleet 是一个由独立站点代理(Bori、Choba、Etche,尼日尔三角洲的三个真实勘测站点)组成的网络。每个代理读取一份地下电力勘测数据,向地下发送电流,测量其回流情况——这是反映地下物质情况的真实物理信号——并根据其站点自身的真实历史数据校准自己的污染风险阈值。这个数值不是从其他任何地方复制的。编排器负责监测在时间窗口内是否有相同的风险特征出现在多个站点。

这是我参加 Google All Things Agentic 黑客松“Fortified Enterprise Fleet”赛道的作品。架构规范性占该赛道 30% 的分数。证明其确实在 Google Cloud 上运行则占另外的 30%。因此,一个仅仅看似修复的 Bug,在审阅者真正阅读其状态管理故事时,是绝对过不了关的。

审视那些已经成功的部分

在理解了真正的故障模式后,我开始用同样的方式审查每一个早期的成功案例,不仅仅是关联告警。

站点列表本身来自原始规格说明:Bori、Ogbogoro、Onitsha。我差点就直接基于此构建。通过与我先前项目的数据溯源记录快速核对,发现 Ogbogoro 的源论文已数月无法访问,DNS 解析失败,而非笔误;Onitsha 则始终只有一个来自搜索摘要的粗略估计范围,用于生成合成样本,从未有过真实的勘测数据。原始三个站点中的两个没有真实的地下数据可供校准。对于一个核心卖点是“根据每个站点真实观测值校准”的项目来说,那将是一个看起来一模一样但毫无意义的演示。于是我将其替换为 Bori、Choba、Etche。三个站点都有完整的、独立的、已发表的真实勘测记录。

关联 Bug 得到了真正的修复,而非补丁。最近事件状态从进程内存迁移到了 Firestore,这与存储每个站点独立勘测历史的数据库是同一个,因此我并非为这一个问题引入第二种独立的共享状态机制。现在每个实例都从同一个共享记录中读取和写入,而不是依赖流量碰巧落在一个实例上的偶然性。我用唯一能证明一切的方式进行了验证:使用全新的站点 ID,在两次独立的运行中实时提交数据,亲眼见证一个新的关联告警两次都基于共享存储正确触发,而不是基于某个碰巧还热着的实例。

真正的脉络

“它运行成功了”和“它是正确的”并非同一项主张。现场演示会欣然让你混淆两者。它证明了你的理想路径曾执行过一次。它无法证明该机制在你未曾遇到的条件下依然成立。修复措施很无聊:在每次成功后都停下来,问清楚具体是什么让它成功,然后再决定它是否完成了。

最终落地情况

VES Fleet 部署在 Cloud Run 上,由 Firestore 和 Pub/Sub 支持。这三者都不是默认选择。站点代理在升级时发布一个事件,而不是由编排器定时轮询 Firestore 中的新行,因为“整个集群跨站点监测模式”应该是一个对真实消息做出反应的真实订阅者,而不是一个大多数时候足够快的定时任务。

Gemini,通过 Google 的 Agent Development Kit,只承担一项工作:为确定性代码已经做出的决策草拟一个人类可读的摘要。它从不重新推导风险数值本身。一个决定站点是否需要升级的数字,不应该在每次调用时由模型重新推导。这与值得彻底修复关联 Bug 而不是带病上线是同样的道理。

这里值得精确表述,而非概括:这四者中有三个是不可或缺的,我可以直接指出。移除 Firestore、Pub/Sub 或 Cloud Run 中的任何一个,上游都会中断,上面那个 Bug 就是实际证明。Gemini 也是真实的,它在每次案例升级时都完成实际工作,但在结构上并非同样不可或缺。移除它,所有标记、门控和关联告警仍然会以完全相同的方式触发。只是需要人工来撰写摘要,而不是由系统草拟一份。

十五项测试通过,包括关联测试套件,现在它们针对共享的 Firestore 存储运行,而不是那个靠运气成功的进程内存列表。关联告警触发是因为状态真正共享了,而不是因为 Cloud Run 那天碰巧如何路由了流量。

我不知道在这个构建中还有什么其他部分是以我未曾核查的原因通过的。以这样的注释结束并不舒服。但这是诚实的。


原文:https://dev.to/dannwaneri/my-cloud-run-multi-agent-fleet-passed-its-demo-the-architecture-was-still-wrong-1p (作者 @dannwaneri)

发布评论
全部评论(0)