博客

捕获发布后立即崩溃的应用

9 月 25 日,有三次发布被标记为成功,但应用的 API 在每次启动后几秒钟就崩溃了。由于这些发布“成功”了,因此没有运行回滚;几分钟后,后台检查将它们判定为失败,整个网站则返回了 404。健康检查统计崩溃次数时,所用的数据来自托管平台的事件列表——该列表每台机器只保留最近五条事件,因此一旦发生崩溃循环,列表就会被填满,计数也就永远不会增长。现在,健康检查改为比较最新一次崩溃的时间。如果发布出现崩溃循环,它就会失败,并恢复到之前的版本。

发布在等待什么

当你在 Mythex 上发布一个带后端的应用时,新版本会部署到我们托管平台的机器上,然后由健康检查来判定这次发布是成功上线还是失败。如果失败,回滚会把之前的版本恢复回来。

难点在于,“已启动”和“正在提供服务”并不是同一回事。平台只要机器启动了,就会将其报告为已启动。而一个在启动后一秒钟就崩溃的应用,会被立即重启,过不了多久又会被显示为已启动。因此,随着时间推移,健康检查逐渐叠加了几层逻辑:

  1. 多看几次。 机器显示为已启动之后,稍等片刻再看一次。启动时的崩溃,往往会在第二次检查时暴露出来。
  2. 留意崩溃循环。 如果平台报告某台机器反复崩溃,并且它已经放弃重启,就判定失败。
  3. 统计本次发布开始以来的崩溃。 两次“已启动”的检查可能恰好跨越一次重启。因此,如果本次发布开始之后发生过任何崩溃,就再看第三次;如果第三次看到的崩溃数量比第二次多,就说明应用并没有稳定运行。

这里失效的正是第三项检查。

为什么计数始终不变

崩溃信息来自每台机器的事件列表:包括启动、退出和重启。平台每台机器只保留最近五条事件。

设想一个应用在每次启动后 2.5 秒就崩溃,其中一个应用正是如此。每个周期都会新增一次崩溃和一次启动。过了几个周期,列表就满了。从那时起,每个新事件都会把一条旧事件挤出去。列表是向前滑动的,但它总是保持大致相同的组合:几次崩溃,几次启动。

因此,“本次发布开始以来的崩溃次数”在每次检查时都返回相同的数字。第二次检查看到的可能是两次崩溃,第三次检查看到的也是两次——虽然是不同的崩溃,但数量相同。检查于是得出结论:崩溃已经停止,并放行了这次发布。

9 月 25 日,这种情况在两个应用上发生了三次。每一次都是这样:

  • 发布被标记为已上线,
  • 没有运行回滚,因为没有任何失败被记录,
  • 我们的对账器(一个事后检查部署状态的后台任务)几分钟后将该部署判定为失败,
  • 整个网站返回了 404。

一次能及时失败的发布是可以恢复的:回滚会把之前的版本恢复回来。而一次几分钟后才失败、并且先前已被宣布为成功的发布,则已经跳过了它的回滚。

我们如何发现它

我们在本地复现了这个问题:拿一个正常工作的 API,让它进入休眠,然后用一个会在启动时崩溃的改动重新发布。健康检查将其标记为已上线。

这与生产环境的情况一致:在这三次发布中,应用在每次启动后几秒钟就会死亡,然而健康检查所比较的崩溃计数,在两次检查之间从未增加。

修复方案:比较最新一次崩溃,而不是计数

现在,健康检查不再统计崩溃次数,而是查看本次发布开始以来最近一次崩溃的时间。

如果第二次检查显示本次发布开始之后发生过任何崩溃,检查就会等待并进行第三次查看。如果第三次看到的最新崩溃时间晚于第二次看到的最新崩溃时间,说明机器在两次检查之间又崩溃了。它并没有稳定运行,发布会失败,并给出提示:机器自发布以来反复崩溃,并且仍在不断重启。

无论事件列表有多短,这种方式都有效。一个只保留五条事件的滑动窗口,可能掩盖崩溃的总次数,但无法掩盖刚刚又发生了一次崩溃——因为最新的事件始终会被保留。

修复之后,本地复现的情况表现正常:发布失败,之前的镜像被恢复。我们还添加了一个测试来模拟平台的行为——每次检查都会新增一次崩溃和一次启动,并把列表裁剪为五条——并验证结论是失败,而不是通过。

我们的收获

  • 了解你所统计的数据的结构。 对一个有上限的列表做计数,一旦列表被填满,计数就不再有意义。这个上限并非隐藏的;只是我们当初没有围绕它来设计检查。
  • 优先问“有没有发生新的事情”,而不是“发生了多少次”。 最新的时间戳在截断之后依然有效,而总数则不然。
  • 迟到的失败比早到的失败更糟。 同一个有问题的构建,如果发布失败并回滚,危害不大;但如果它先被宣布为成功,就会让整个网站宕机。
  • 在真实条件下复现。 这个 bug 需要一台机器已经崩溃了足够多次,以至于事件列表被填满。在测试中只崩溃一次,是发现不了它的。

这项修复与同一天的另一项修复相配合,后者确保回滚会把旧版本恢复回来,而不是将其删除:失败的重新发布永远不会删除正常运行的后端。如果你自己的应用因为启动时崩溃而无法发布,发布故障排查文档,以及我们关于调试 AI 构建应用的指南,是很好的起点。

Mythex · Pricing · 用 AI 构建任何东西 · 网站和应用模板 · Mythex 对比 · AI 应用构建术语表 · 免费的 AI 应用构建工具 · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 繁體中文(香港) 繁體中文(台灣)