简体中文
  • 事后分析
  • 云服务
  • 事件

事后分析:用户登录时发生了意外的 500 错误

2024年7月18日身份验证服务返回意外500错误的事件报告。

Charles
Charles
Developer

概要

2024年7月18日,Logto Cloud 的身份验证服务发生了 500 内部服务器错误,导致服务中断。

  • 受影响的用户:所有尝试进行身份验证的 Cloud 用户
  • 受影响的地区:欧洲和美国
  • 严重性:严重,扰乱了用户的登录体验

根本原因

在最近的 Cloud 部署期间,数据库架构中的一个重大更改导致登录体验 API 在预发布和生产环境之间的过渡过程中失败。

时间线

  • 2024-07-18 08:57 (UTC): 对 Logto Cloud 进行了更新部署
  • 2024-07-18 09:28 (UTC): 第一个用户报告了 500 错误
  • 2024-07-18 09:31 (UTC): 开发团队确认了问题并开始调查
  • 2024-07-18 09:32 (UTC): 问题自动解决
  • 2024-07-18 09:40 (UTC): 找到根本原因

事件分析

什么是数据库重大更改,为什么会发生?

我们目前正在开发一个名为“自定义 UI” 的新功能,允许用户使用他们自己的网页来自定义 Logto 的登录体验。此功能需要在 sign-in-exp 表中添加新列以存储自定义 UI 配置。

由于开发过程中的需求变化,该功能的发布被推迟,但架构更改的第一部分已经在几周前部署到生产环境,尽管尚未投入使用。 数据库列的更新是在 此 PR 中引入的。

不幸的是,此更改不具有向后兼容性,导致旧代码的 API 请求在与新数据库通信时失败。

我们如何部署新的 Logto Cloud 版本?

部署新版本的 Logto Cloud 时,我们首先将其部署到预发布环境,然后交换预发布和生产环境。 过程如下:

  1. 运行数据库更改脚本并更新数据库。
  2. 将新源码部署到预发布服务器。
  3. 运行预发布服务器并进行测试。
  4. 交换预发布和生产服务器,使“预发布”成为“生产”,以便用户可以在没有停机的情况下访问新版本。

然而,两个环境共享同一个数据库,整个过程需要时间。所以在数据库更新和环境交换之间的时间窗口中,在线用户仍然处于生产环境的旧代码,但尝试与新数据库通信。

这是事件的根本原因,也是为什么问题在 35 分钟内自动解决的原因。

为什么在代码审核过程中没有解决这个问题?

我们确实有一个 CI 任务来检查数据库更改的向后兼容性。然而,以前合并 PR 之前不要求通过 CI 检查。这是因为大多数情况下开发阶段通常在几个冲刺内较短,而架构更改的第一和第二部分通常包含在同一发布阶段。 这次,功能发布被推迟,将架构更改分布在两次发布中。开发人员认为 CI 失败是预期的,并通知审核人员这不应阻止 PR 的合并。 确实存在沟通差距,最终在未提供任何必要的向后兼容性支持的情况下合并了 PR。

经验教训

  • 在对数据库架构进行重大更改时,我们应该始终考虑与旧版本源码的向后兼容性。
  • 更改数据库列时,我们应该避免直接在架构中更改,而应该使用弃用和迁移方法。
  • 开发人员应对发布过程和时间表有更多的意识。

纠正和预防措施

  • ✅ 现在要求数据库向后兼容性 CI 检查通过后才能合并包含架构更改的 PR。
  • ✅ 强调团队内部向后兼容性的重要性。