換到更大的工作區,又不讓任何人等待
每個 Mythex 專案都有自己的工作區:一台小型雲端電腦,代理程式在上面寫程式,你的應用程式預覽也在上面執行。我們已經把新工作區的記憶體從 1 GB 提高到 2 GB,但舊的工作區仍維持 1 GB。在我們檢查的那一天,約有四分之一的工作區是這樣。我們第一次的修正,是在下次開啟專案時把它移到更大的工作區。結果在它上線的第一天,就讓一位使用者等了七分鐘。於是我們為它設定了硬性的時間上限,然後乾脆把遷移從開啟專案的流程中完全拿掉。
為什麼舊的工作區仍然很小
我們的沙盒供應商會在工作區建立時決定其大小,並在每次暫停與恢復時保留這個設定。修改範本(也就是新工作區所依據的配方)只會影響在變更之後建立的工作區,不會調整既有的工作區。
這一點很重要。其中一個小型工作區在 git push 時,於預覽啟動的同時用光了記憶體,之後 11 分鐘都無法回應。一次發布也因此失敗。
第一次嘗試:在喚醒時移動專案
工作區在沒有人使用時會暫停,並在開啟專案時喚醒。喚醒似乎是移動專案的最佳時機,因為此時還沒有人在工作。
移動流程如下:
- **檢查大小。**如果工作區小於 2 GB,就進行移動;如果無法得知大小,就不做任何事。
- **不打擾發布。**發布會讀取工作區的檔案,因此若有發布正在進行,就跳過移動。
- **打包專案。**把專案中的所有東西打包成壓縮檔,包括它的 git 歷程(也就是專案擁有的每一個檢查點),以及屬於擁有者的應用程式
.env檔案;但不包含已安裝的相依套件(node_modules),因為它們可以重新安裝。 - **直接複製過去。**把壓縮檔從舊工作區串流傳輸到一個全新的 2 GB 工作區,這樣它就永遠不需要放進我們自己伺服器的記憶體中。
- **切換前比對。**在兩個工作區中分別計算檔案數、讀取最新的檢查點,並計算檢查點數量。只有三者全部相符時才會切換。
- **任何失敗都保留舊的工作區。**任何錯誤或比對不符,都會捨棄新的工作區,並照舊在原本的工作區中開啟專案。
比對中有一個細節,比乍看之下更重要。這項檢查是以管理員帳號執行的,而 git 會拒絕讀取由其他使用者擁有的儲存庫。兩邊都沒有輸出任何東西,而「沒有輸出」與「沒有輸出」相符,因此檢查在完全沒有比對任何歷程的情況下就通過了。我們告訴 git 信任該目錄,並新增了一個測試,確保這種情況不會再次發生。
第一天出了什麼問題
在正式環境上線的第一天,打包某個專案時碰上了五分鐘的指令逾時,發生在喚醒過程之中。擁有者等了七分鐘,工作區才打開。而且因為移動失敗,專案仍然是小型的,所以下次開啟時還會再試一次,讓他們再等一次。
在使用者開啟自己的專案時讓他們等待的遷移,是一筆很糟的交易。把它放在喚醒時執行,原本的目的就是讓人察覺不到。
第二次嘗試:設定硬性預算
同一天,我們改了四件事:
- **整個移動只給一分鐘。**每個步驟(檢查大小、打包、建立新工作區、複製、解壓縮、比對)共用同一個 60 秒的預算。預算用完時,專案就在舊的工作區中開啟。
- **停止工作,而不只是停止等待。**如果我們放棄了,但打包作業仍在擁有者即將使用的工作區內執行,那就沒有解決問題。現在每個打包指令都會在預算結束前不久,於工作區內部被終止。如果新工作區在我們放棄之後才完成,就會被丟棄。
- **不讓擁有者等待清理。**暫存壓縮檔的刪除,現在改在背景進行。
- **不要在每次開啟時重試。**無法移動的專案會被擱置 24 小時,因此一次失敗最多只會造成一天一次的延遲,而不是每次開啟都延遲。
第三次嘗試:把它從喚醒流程中拿掉
這樣做讓最壞的情況變成一分鐘。但一分鐘仍然是一分鐘,而且我們意識到,移動根本不需要出現在任何人的使用路徑上。
現在已經不會再建立 1 GB 的工作區。因此這不是一個持續進行的流程,而是一次性的工作,對象是一份固定的工作區清單。把它放在喚醒流程裡,等於讓真實的人承擔每一次緩慢移動的代價,而我們得知某個工作區無法移動的唯一方式,就是有人剛剛為此等待過。
因此我們把移動從喚醒流程中完全移除。開啟專案的行為與以前相同。剩下的小型工作區,則改由有人監督的批次作業處理:沒有人在等待,而無法移動的工作區會出現在批次作業的報告中,讓我們可以仔細查看,而不是出現在擁有者面前。
我們的收穫
- **調整大小不一定可行。**當平台在建立時就固定了大小,提高預設值只對新建立的東西有幫助。舊的東西需要另行規劃。
- **「還沒有人在用」仍然代表有人在等。**在進入產品的途中所做的工作,是有人看得見的工作。
- **對使用者路徑上的任何事情設定預算,並在預算用完時停止工作。**在我們這一端逾時,而指令卻在別處繼續執行,只會讓問題換個地方發生。
- **一次性的遷移應該放在一次性的工作中。**把它藏在日常操作裡,寫起來比較省事,執行起來卻更昂貴。
- **測試你的安全檢查。**一個什麼都沒比對的比較,看起來和通過了的比較一模一樣。
如果你在 Mythex 上建置應用程式,你不需要做任何事:我們的目標只是讓工作區因記憶體不足而當機的情況減少,同時開啟專案的速度與以前一樣快。工作區如何暫停與喚醒,已在文件的私人工作區中說明。若想看另一則關於記憶體不足的故事,請參閱藏在進度標籤中的記憶體不足當機。