部落格

凍結我們伺服器的那個缺少的交換檔

9 月 24 日,我們的一台正式環境伺服器停止回應。負載平衡器將它標記為不健康,我們的遠端命令工具也無法連上它——但沒有任何東西當機,也沒有因為記憶體用量過高而被終止。伺服器正在抖動(thrashing):沒有交換空間,而且容器被允許使用的記憶體總和超過機器實際擁有的量,Linux 把時間都花在逐出並重新讀取它執行所需的檔案上,幾乎沒有進展。在每台伺服器上加入一個 2 GB 的交換檔就修好了。更有意思的教訓則與健康檢查有關。

「卡住」看起來是什麼樣子

  • 負載平衡器對該伺服器的健康檢查逾時。
  • 透過 AWS Systems Manager 送出的命令停留在「Pending」,從未執行。
  • 紀錄中沒有記憶體不足的終止。沒有任何程序死掉。

一週前,我們剛把正式環境遷移到較小的 ARM 伺服器,每台有 2 GB 記憶體。我們的預發佈伺服器——更小的那台——在部署時解壓縮容器映像檔的過程中,也以相同的方式凍結了。

為什麼沒有記憶體錯誤?

Linux 只有在真的耗盡可回收的記憶體時,才會終止程序。在那之前,它會從 頁面快取——保存在 RAM 中的檔案副本,包括每個執行中程式的程式碼——回收記憶體。

在我們的伺服器上,容器的記憶體上限加總約為 3.3 GB,而機器實際可用的約為 1.8 GB。通常它們不會同時用到上限。但當它們同時用到時,核心會不斷把程式碼從快取中逐出以騰出空間,而那些程式碼一旦再次執行,就又得從磁碟讀回來。這種循環——抖動——可以讓機器幾乎完全失去回應,同時從技術上說又沒有耗盡記憶體。因此沒有任何東西被終止,也沒有任何東西能夠復原。

沒有交換空間時,核心沒有地方放置已分配但很少使用的記憶體,因此只能改從快取中拿。

修正方式

伺服器的啟動腳本現在會在每次開機或修復伺服器時,建立一個 2 GB 的交換檔,並將 swappiness 設為較低的值(10)。較低的 swappiness 表示核心仍然偏好把工作記憶體保留在 RAM 中,但很少被觸碰的頁面可以移到磁碟,而不必把程式碼逐出快取。我們已在正式環境的兩台伺服器與預發佈環境上即時套用,部署流程在每次正式部署時都會重新發佈啟動腳本,因此被替換的伺服器也會取得它。

更讓我們擔心的部分:不健康的伺服器留了下來

我們的伺服器群組使用的是 EC2 健康檢查——「機器還在運作嗎?」——而不是 負載平衡器健康檢查——「它還在回應請求嗎?」。因此,對群組而言,一台負載平衡器已經放棄的伺服器仍然是健康的。它永遠不會被替換。正式環境會悄悄地只靠一台伺服器運作,直到有人注意到並重新開機另一台。

把群組改用負載平衡器健康檢查聽起來是顯而易見的解法,但對我們來說並不直接:在部署期間,伺服器會刻意以錯誤回應它們的健康端點,好讓負載平衡器把它們排空(參見 我們如何把部署降到零 502)。一個會因為該訊號而替換伺服器的群組,會在每次部署的中途替換它們。

因此目前我們在部署檢查清單中加入了一個步驟:每次部署後,檢查負載平衡器上每個目標的健康狀態,而不只是確認部署工作是否通過。如果發給某台伺服器的命令停在「Pending」,表示它正在抖動——重新開機它;它已經不在輪替中了。

我們從中學到什麼

  • 「沒有當機」不等於「健康」。 抖動不會產生錯誤,只會產生極度緩慢的狀況,直到機器停止回應。
  • 小型伺服器需要交換空間。 即使只有一點點,搭配較低的 swappiness,也能讓核心有地方放置冷門的記憶體。
  • 加總超過機器容量的記憶體上限是一場賭注。 有時你會輸。要知道你什麼時候下了這個賭注。
  • 要知道你的自動擴展信任哪一種健康檢查。 只問「VM 是否開機?」的健康檢查,不會替換已經停止運作的伺服器。

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