部落格

失敗的重新發布絕不會刪除運作中的後端

9 月 25 日,一次失敗的重新發布刪掉了某個應用程式的後端,而那個後端已經穩定運作了大約兩個半小時。負責復原失敗發布的程式碼,把發布過程中碰過的每一個伺服器應用程式都移除了,包括在發布開始前就已經在提供服務的應用程式。現在只有發布時新建的應用程式會被刪除;已經存在的應用程式會被還原到它在發布前執行的確切版本。同一天的另外兩項修正,確保復原在託管平台自己的部署工具失敗時也會執行,並且健康的應用程式不會只因為當時處於休眠狀態就被判定為失敗。

後端如何發布

當你的 Mythex 應用程式包含後端(也就是 API 或伺服器,而不只是靜態檔案)時,發布會先用 Dockerfile(將應用程式打包成映像檔的配方)建置它,接著把這個映像檔部署到我們託管平台上的機器。然後健康檢查會等待新版本真正啟動並穩定運作,發布才會被標示為上線。

過程中只要有任何環節失敗,就會執行復原來撤銷變更。把復原做對,比發布流程中幾乎任何其他部分都重要,因為它正是在某件事已經出錯時才會執行。

問題一:復原刪掉了本該還原的東西

復原程式會記錄一份清單,列出發布部署過的伺服器應用程式;一旦失敗,就把清單上的每個應用程式全部銷毀。對第一次發布來說,這樣做沒有問題:應用程式是剛剛才建立的,沒有任何東西依賴它,刪除後就回到原來的狀態。

但對重新發布來說,這樣做就完全錯了。應用程式已經存在,並且正在為真實的訪客提供服務。9 月 25 日,一個已經上線約兩個半小時的應用程式 API,就因為一次失敗的重新發布而被刪除。

同一段程式碼裡還藏著第二種失敗模式。如果刪除沒有成功,壞掉的新映像檔就會留在機器上,而我們卻告訴擁有者他們目前的網站仍在線上。健康檢查失敗時,新映像檔早已部署到每一台機器上。什麼都不做,並不等於已經復原。

修正方式:只銷毀自己建立的,其餘還原

現在每次發布都會為它所碰觸的每個伺服器應用程式記錄:

  • 這次發布是否建立了它,以及
  • 如果不是,它在發布前執行的是哪個映像檔。

復原失敗時,每個應用程式會依下列三種情況處理:

  1. **由本次發布建立:**照舊銷毀。
  2. **原本就存在,且已知先前的映像檔:**用相同設定重新部署先前的映像檔。不需要建置,只是把映像檔換回去。
  3. **原本就存在,但先前的映像檔未知:**不予處理。已存在的應用程式永遠不會被刪除,即使我們無法還原它。

這些規則是一個小型的純函式,並附有自己的測試,因此只要有測試失敗,決策就無法退回「全部銷毀」的做法。

問題二:部署工具可能在我們記下如何復原之前就失敗

修正之後不久,我們發現還有一個缺口。託管平台的部署工具會自行執行冒煙測試:如果新機器當機,它就會以錯誤結束。但這個動作發生在新映像檔已經部署到機器上之後。

我們的程式直到部署工具成功返回後,才會把應用程式登記到復原清單。當工具本身讓部署失敗時,應用程式還沒有進入復原清單,因此什麼都不會被還原。在我們的預備環境中,一次壞掉的重新發布就讓壞掉的映像檔繼續提供服務。

修正方式:先登記復原,再開始動作

現在,應用程式一經準備好、還沒有把任何東西部署上去之前,就會登記到復原清單,並記下它是否為新建立、以及它原本執行的映像檔。不論之後哪個步驟失敗,復原都知道該還原什麼。我們在本機驗證過:重新發布在部署工具自己的冒煙測試中失敗,而先前的版本仍持續回應請求。

問題三:休眠中的應用程式被判定為「從未啟動」

Mythex 上已發布的應用程式閒置時會休眠,以節省你的點數。重新發布會讓休眠的機器維持停止狀態,因此健康檢查必須把它喚醒。過去的做法是請求平台啟動機器一次,然後忽略回應。

9 月 25 日,那一次啟動請求沒有得到任何結果。一個健康的 API 就這樣停在停止狀態,整整五分鐘的健康檢查期間都沒有起來,最後被判定為「1 台機器從未啟動(最後狀態:stopped)」。

平台有時確實會拒絕啟動。我們在重現這個問題時,平台在我們沒有刻意觸發的情況下回傳了「lease currently held」衝突;而當機器正在更新時,它也會拒絕啟動。

修正方式:持續要求,並主動叫醒

健康檢查現在會:

  • 在等待期間,每 20 秒再次要求啟動停止中的機器,
  • 記錄平台拒絕時的回應內容,
  • 並像一般訪客那樣向應用程式發送一次普通請求。平台的代理在收到請求時會喚醒休眠中的機器。

我們用一個第一次啟動會被拒絕的臨時應用程式,在真實平台上重現了這個問題。修正前,發布在 91 秒後失敗;修正後,20 秒內就完成發布。真正在開機時當機的應用程式仍然會失敗,這是正確的結果。

我們的收穫

  • **復原必須分辨「新建立」與「原本就存在」。**對你建立的東西來說,「復原」就是刪除;對原本就存在的東西來說,「復原」則是還原。把兩者等同看待,正是安全機制刪掉運作中應用程式的原因。
  • **行動之前,先寫下如何復原。**如果只有在某個步驟成功後才記錄復原方式,那麼一個中途失敗的步驟,就沒有可以用來復原的東西。
  • **絕不忽略你所依賴的請求的回應。**一個被忽略的「不行」,就讓一個健康的應用程式變成發布失敗。

同一天的另一項修正是:應用程式在發布後立即當機的攔截機制。若發布在你這一端失敗,請參閱文件中的發布疑難排解。

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 简体中文 繁體中文(香港)