繁體中文(台灣)
  • postmortem
  • cloud-service
  • incident

事後分析:使用者登入時發生意外的 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。

教訓

  • 當資料庫結構發生重大變更時,我們應該始終考慮與舊版本源代碼的向後兼容性。
  • 當修改資料庫列時,我們應避免直接在結構中更改,而應使用棄用和遷移方法。
  • 開發者應該對發布過程和時間安排有更多的認識。

糾正和預防措施

  • ✅ 現在需要在合併包含結構變更的 PR 之前通過資料庫向後兼容性的 CI 檢查。
  • ✅ 強調團隊內向後兼容性的重​​要性。