在設計服務時可以將各種可靠性和彈性功能內建其中,但為了在實踐中確保可靠性,服務還必須在發生可預測的失敗時能夠及時處理。在 Amazon,我們致力於打造可水平擴展和冗餘的服務,因為硬體設計最終會失敗。任何硬碟都具有預期壽命上限,並且任何軟體都容易在某些時刻崩潰。伺服器的運作狀態似乎為二進位:要麼運作,要麼完全不運作,以及無法正常運作。可惜事實並非如此。我們發現,發生錯誤的伺服器不僅會關閉,還可能對系統造成不可預測的損害,有時甚至會造成不成比例的損害。運作狀態檢查會自動偵測並回應此類問題。

本文介紹了我們如何透過運作狀態檢查,來偵測和處理單一伺服器失敗,不進行運作狀態檢查時會發生哪些事情,以及對運作狀態檢查失敗反應過度的系統,如何將小問題演變為完全中斷服務。我們還將憑藉我們在 Amazon 上的經驗,提供有關在各種運作狀態檢查實作之間進行權衡與平衡的見解。

小小失敗,大大影響

我剛在 Amazon 任職軟體開發人員時,負責 Amazon.com 後台的網站呈現機群。在做出變更以新增某些檢測,以及洞察該軟體的運作狀況時,我很抱歉編寫了一個錯誤。該錯誤很少觸發,但當它觸發時,會導致給定的 Web 伺服器,對每個請求呈現空白錯誤頁面。只有重新啟動 Web 伺服器進程,才能修復該問題。我們快速地偵測到該錯誤並復原變更,新增了許多測試,以及改進了程序,以便在今後能發現此類情況。但是,當該錯誤在生產環境中時,大型機群中的一些伺服器因該崩潰狀態而終止運作。
 
導致該錯誤特別棘手的一件事是,伺服器並未意識到其處於不佳運作狀態。另外,伺服器無法將其運作狀態報告給監控系統,因此它不會自動退出服務,也不會觸發常規警報。更糟糕的是,伺服器變得非常快,開始產生空白錯誤頁面,並且速度要比其對等的「運作狀態良好的伺服器」呈現正常網頁的速度要快得多。我們當時使用的負載平衡技術優先於快速伺服器,而非慢速伺服器,因此,它將過多的流量定向至運作狀態不佳的伺服器,這進一步加大了影響。

由於監控涉及量測系統中多個點的錯誤率和延遲,因此觸發了其他警報。這些監控系統和操作程序能作為控制問題的後障,而正確的運作狀態檢查可透過快速偵測失敗並採取行動,從而最大程度地降低此類錯誤的影響。

運作狀態檢查權衡

運作狀態檢查是一種詢問特定伺服器上的服務,是否能夠成功執行工作的方法。負載平衡器會定期向每個伺服器詢問此問題,以確定將流量定向至哪些伺服器是安全的。從佇列中輪詢訊息的服務可能會先問自己運作狀態是否良好,然後再決定從佇列中輪詢更多工作。監控代理程式 (在每個伺服器上或在外部監控機群上執行) 可能會詢問伺服器運作狀態是否良好,以便其可以發出警報,或自動處理發生錯誤的伺服器。

正如我們在網站錯誤範例中看到的那樣,當運作狀態不佳的伺服器處於服務狀態時,它會成比例地降低整個服務的可用性。對於一個由十部伺服器組成的機群,一部運作狀態不佳的伺服器意味著該機群的可用性為 90% 或更少。更糟糕的是,某些負載平衡演算法 (例如「最少請求」),讓最快的伺服器承擔更多工作。當伺服器失敗時,它通常會迅速開始讓請求失敗,透過吸引比運作狀態良好的伺服器更多的請求,在服務機群中造成「黑洞」。在某些情況下,我們透過減慢失敗請求的速度,來配合成功請求的平均延遲,以便新增額外保護,防止出現黑洞。然而,在其他情況下 (例如佇列輪詢器),此問題更難解決。例如,若佇列輪詢器以最快的速度輪詢訊息,則失敗的伺服器也將變成一個黑洞。在用於分配工作的環境如此多樣化的情況下,我們考慮保護部分失敗伺服器的方式因系統而異。

我們發現,伺服器因各種原因獨立失敗,包括磁碟變得不可寫入並導致請求立即失敗,時鐘突然偏斜並導致對相依項的叫用未能通過身分驗證,伺服器無法擷取更新的加密材料並導致解密和加密失敗,關鍵的支援程序因其自身的錯誤、記憶體洩漏和凍結處理鎖死而崩潰。

伺服器也因關聯原因而失敗,導致一個機群中的許多或所有伺服器一起失敗。關聯原因包括共用相依性中斷和大規模網路問題。理想的運作狀態檢查將測試伺服器和應用程式運作狀態的方方面面,甚至可能會驗證非關鍵支援程序是否正在執行。然而,若運作狀態檢查因非關鍵原因而失敗,並且該失敗與伺服器間相關聯,則會出現問題。當伺服器仍然可以執行有用的工作時,若自動化將其從服務中移除,則自動化弊大於利。

運作狀態檢查的困難在於,一方面,進行徹底運作狀態檢查與快速緩解單一伺服器失敗各自的好處,另一方面,在整個機群中因誤報失敗而造成損害,這之間存在著這種矛盾。因此,建構有效的運作狀態檢查所面臨的挑戰之一,即謹慎防範誤報。通常,這意味著圍繞運作狀態檢查的自動化應停止將流量導向至單一錯誤伺服器,但若整個機群似乎都遇到問題,則繼續允許流量通過。

量測運作狀態的方法

伺服器上可能發生很多事情,並且系統中有很多方面可用來量測伺服器的運作狀態。某些運作狀態檢查可以確定地報告,特定伺服器已獨立崩潰,而其他一些則更模糊不清,並在關聯失敗的情況下誤報。某些運作狀態檢查很難實作。其他檢查則是在安裝時,通過 Amazon Elastic Compute Cloud (Amazon EC2) 和 Elastic Load Balancing 等服務實作。每種類型的運作狀態檢查都有其優勢。

活躍度檢查

活躍度檢查可測試與服務的基本連線,以及伺服器程序的狀況。它們通常由負載平衡器或外部監控代理程式執行,並且不了解有關應用程式如何工作的詳細資訊。活躍度檢查通常包含在服務中,並且不需要應用程式編寫者實作任何內容。我們在 Amazon 使用的活躍度檢查的一些範例包括:

• 確認伺服器正在偵聽其預期連接埠,並接受新 TCP 連線的測試。
• 執行基本 HTTP 請求,並確保伺服器以 200 狀態碼回應的測試。
• Amazon EC2 的狀態檢查,用於測試任何系統運作所必需的基本內容,例如網路可連線性。

本機運作狀態檢查

本機運作狀態檢查比活躍度檢查更進一步,可驗證應用程式是否能運作。這些運作狀態檢查將測試未與伺服器對等共用的資源。因此,它們不太可能在機群中的許多伺服器上同時失敗。這些運作狀態檢查將測試以下各項:

• 無法寫入磁碟或從磁碟讀取 - 可能會傾向於認為無狀態服務不需要可寫磁碟。然而,在 Amazon,我們的服務傾向於將其磁碟用於監控、記錄和發佈異步計量資料之類的事情。
• 關鍵程序損毀或崩潰 - 某些服務使用伺服器上的代理程式 (類似於 NGINX) 接收請求,並在另一個伺服器程序中執行其業務邏輯。活躍度檢查可能僅測試代理程序是否正在執行。本機運作狀態檢查程序可能會從代理傳遞至應用程式,以檢查其是否正在執行並正確回覆請求。有趣的是,在本文開頭的網站範例中,現有的運作狀態檢查足夠深入到能確保呈現程序正在執行並回應,但不足以深入到確保其正確回應。
• 缺少支援程序 - 缺少監控精靈的主機可能會讓營運商「盲目運作」,並且不了解其服務的運作狀態。其他支援程序將推送計量和計費用量記錄,或接收憑證更新。支援程序崩潰的伺服器會以細微的、難以偵測的方式讓功能面臨風險。

相依性運作狀態檢查

相依性運作狀態檢查是對應用程式與其相鄰系統進行互動的能力的徹底檢查。理想情況下,這些檢查可以發現伺服器本機問題,例如到期的憑證,這些問題可阻止伺服器與相依項進行互動。但是,當相依項本身存在問題時,它們也可能會產生誤報。由於這些誤報,我們必須謹慎對待相依項運作狀態檢查失敗的回應方式。相依項運作狀態檢查可能會測試以下各項:

• 錯誤的設定或過時的中繼資料 - 若某個程序異步尋找對中繼資料或組態的更新,但伺服器上的更新機制崩潰,則伺服器可能會與對等伺服器嚴重不同步,並且行為無法預測且未經測試。但是,當伺服器有一陣子看不到更新時,它不知道更新機制是否崩潰,或者中央更新系統是否停止將更新發佈至所有伺服器。
• 無法與對等伺服器或相依項進行通訊 - 已知奇怪的網路行為會影響機群中伺服器子集與相依項進行通訊的能力,而不影響將流量傳送至該伺服器的能力。軟體問題,例如鎖死或連線集區中的錯誤,也可能會阻礙網路通訊。
• 其他需要程序彈跳的非常規軟體錯誤 - 鎖死、記憶體洩漏或狀態損毀錯誤可能會使伺服器產生錯誤。 

異常偵測

異常偵測會檢查機群中的所有伺服器,以確定任何伺服器與其同級伺服器相比是否表現異常。透過彙總每個伺服器的監控資料,我們可以不斷地比較錯誤率、延遲資料或其他屬性,以尋找異常伺服器,並自動將其從服務中移除。異常偵測可以發現機群中伺服器無法偵測自身的差異,例如:

• 時鐘偏斜 - 尤其是在伺服器處於高負載時,已知其時鐘會突然且急劇偏斜。安全措施,如用於評估 AWS 已簽署請求的措施,要求用戶端時鐘上的時間在實際時間的五分鐘範圍內。若不是,則 AWS 服務請求失敗。
• 舊代碼 - 若伺服器與網路中斷連線,或長時間斷電後再重新連線,則該伺服器可能會執行危險的過時代碼,而該代碼與其他機群不相容。
• 任何非預期的失敗模式 - 有時伺服器會以返回錯誤的方式失敗,從而將錯誤識別為用戶端錯誤 (HTTP 400 而非 500)。伺服器可能會變慢而不是失敗,或者其回應速度可能比對等伺服器快,這表明它們正在向其叫用者返回錯誤回應。對於非預期失敗模式,異常偵測的包羅萬象令人不可思議。

實際上,只有少數幾件事情適用於異常偵測:

• 伺服器應當做大致相同的事情 - 若我們將不同類型的流量明確路由至不同類型的伺服器,則這些伺服器的行為可能不夠相似,無法偵測異常值。然而,若我們使用負載平衡器將流量定向至伺服器,則它們可能會以類似的方式做出回應。
• 機群應相對同質 - 在包含不同執行個體類型的機群中,某些執行個體可能比其他執行個體慢,這會錯誤地觸發被動的不良伺服器偵測。若要解決此情況,我們可按執行個體類型整理指標。
• 必須報告錯誤或行為差異 - 因為我們依靠伺服器本身來報告錯誤,所以當其監控系統也崩潰時,會發生什麼? 幸運的是,服務的用戶端是新增檢測的好地方。Application Load Balancer 之類的負載平衡器會發佈存取日誌,其中顯示每個請求都聯絡了哪個後端伺服器、回應時間,以及該請求成功還是失敗。 

對運作狀態檢查失敗做出安全回應

當伺服器確定其運作狀態不佳時,可以採取兩種措施。在最極端的情況下,它可以在本機決定不應執行任何工作,並透過讓負載平衡器運作狀態檢查失敗,或停止輪詢佇列來使其自身停止服務。伺服器可以做出回應的另一種方式是,通知中央授權單位其有問題,然後讓中央系統決定如何處理該問題。中央系統可以安全地解決問題,而不會讓自動化導致整個機群癱瘓。

有多種方法可以實作和回應運作狀態檢查。這部分內容介紹了我們在 Amazon 使用的一些模式。

失敗開啟

某些負載平衡器可用作智慧型中央授權單位。當個別伺服器作狀態檢查失敗時,負載平衡器將停止向其傳送流量。但是,當所有伺服器運作狀態檢查同時失敗時,負載平衡器將無法開啟,從而導致流量流向所有伺服器。我們可以使用負載平衡器,對相依性運作狀態檢查的安全實作提供支援,其中可能包括查詢其資料庫並進行檢查,以確保其非關鍵支援程序正在執行。

例如,若沒有任何伺服器報告為運作狀態良好,則 AWS Network Load Balancer 將無法開啟。若可用區域中的所有伺服器均報告運作狀態不佳,則其也會避開狀態不佳的失效可用區域。(如需有關使用 Network Load Balancer 進行運作狀態檢查的詳細資訊,請參閱 Elastic Load Balancing 文件。) 我們的 Application Load Balancer 與 Amazon Route 53 一樣,也支援失敗開啟。(如需有關使用 Route 53 設定運作狀態檢查的詳細資訊,請參閱 Route 53 文件。)

當我們依靠失敗開啟行為時,確保測試相依項運作狀態檢查的失敗模式。例如,考慮將伺服器連線至共用資料存放區的服務。若該資料存放區變慢或以低錯誤率回應,則伺服器的相依項運作狀態檢查可能偶爾會失敗。這種情況導致伺服器進入和退出服務狀態,但不會觸發失敗開啟閾值。使用這些運作狀態檢查來推理和測試相依項的部分失敗,對於避免以下情況非常重要︰由於失敗而可能導致深度運作狀態檢查讓情況變得更糟。

儘管失敗開放是一種有益的行為,但在 Amazon,我們傾向於對無法在所有情況下充分推理或測試的事情表示懷疑。我們尚未提出以下情況一般證明︰錯誤開啟如我們預期的那樣,會觸發系統或該系統相依項中所有類型的過載、部分失敗或灰色失敗。由於此限制,Amazon 團隊傾向於將其快速作用的負載平衡器運作狀態檢查,限制為本機運作狀態檢查,並依靠集中式系統對更深的相依項運作狀態檢查謹慎回應。這並非表示我們不使用失敗開啟行為,也並未證明其在特定情況下有效。但是,當邏輯可在大量伺服器上快速發揮作用時,我們對待該邏輯非常謹慎。

無斷路器情況下的運作狀態檢查

允許伺服器對自己的問題做出回應似乎是最快、最簡單的復原途徑。然而,若伺服器的運作狀態有誤,或看不到整個機群的情況,這也是最危險的路徑。當整個機群中的所有伺服器同時做出相同的錯誤決策時,可能會導致相鄰服務之間的串聯失敗。該風險使得我們需要權衡。若運作狀態檢查和監控之間存在差距,則伺服器可能會降低服務的可用性,直至偵測到問題為止。然而,該方案可避免由於整個機群發生非預期的運作狀態檢查行為,而導致服務完全中斷。

當我們沒有內建斷路器時,以下是實現運作狀態檢查的最佳實務:

• 設定工作生產者 (負載平衡器,佇列輪詢執行緒) 以執行活躍度和本機運作狀態檢查。只有當伺服器遇到該伺服器本機肯定存在的某些問題 (例如磁碟損壞) 時,負載平衡器才會自動讓其停止服務。
• 設定其他外部監控系統,以執行相依項運作狀態檢查和異常偵測。這些系統可能會嘗試自動終止執行個體,或者向操作人員發出警報或讓其介入。

當我們建構系統對相依項運作狀態檢查失敗自動做出回應時,必須內建適當數量的閾值,以免自動化系統非預期地採取嚴厲措施。運作具狀態伺服器的 Amazon 團隊,如 Amazon DynamoDB、Amazon S3 和 Amazon Relational Database Service (Amazon RDS),對於伺服器更換具有重要的耐用性要求。他們還設定了謹慎的速率限制和控制回饋迴圈,以便在超過閾值時自動停止並讓人員介入。當我們建構這種自動化時,必須確保當伺服器的相依項運作狀態檢查失敗時,我們會注意到該情況。對於某些指標,我們依靠伺服器將其各自的狀態,自我報告給中央監控系統。為了彌補伺服器崩潰而無法報告其運作狀態的情況,我們還主控與其建立連線,以檢查其運作狀態。 

優先考慮運作狀態

尤其是在過載情況下,對於伺服器而言,將其運作狀態檢查優先於其常規工作非常重要。在此情況下,運作狀態檢查失敗或回應緩慢,會導致電力不足情況更加嚴重。 

當伺服器的負載平衡器運作狀態檢查失敗時,它要求該負載平衡器立即將其從服務中刪除,且花費不少的時間。當單一伺服器失敗時,這不是問題,但在服務流量激增的情況下,我們最不想做的是縮小服務規模。在過載期間讓伺服器停止運作,可能會導致螺旋式下降。迫使其餘伺服器佔用更多流量,將使其更有可能變得超載,還會導致運作狀態檢查失敗,並進一步縮小機群。

問題不在於過載的伺服器在過載時會返回錯誤,而在於伺服器沒有及時回應負載平衡器的 ping 請求。畢竟,負載平衡器運作狀態檢查設定有逾時,就像其他任何雲端服務叫用一樣。掉電的伺服器回應速度很慢,原因有很多,其中包括 CPU 爭用較高、垃圾收集器週期長,或僅在工作執行緒中耗盡。服務需要設定為預留資源,以及時回應運作狀態檢查,而不是接受過多的其他請求。

幸運的是,我們遵循一些簡單的組態最佳實務,來協助防止這種螺旋式下降。iptables 之類的工具,甚至某些負載平衡器,都支援「最大連線數」的概念。 在這種情況下,作業系統 (或負載平衡器) 會限制與伺服器的連線數量,以使伺服器程序不會被並行請求淹沒,因為並行請求會降低伺服器的速度。

當服務由支援最大連線數的代理或負載平衡器作為前端時,使 HTTP 伺服器上的工作執行緒與代理中的最大連線數相符似乎是合乎邏輯的。不過,該組態會為掉電期間的螺旋式下降設定服務。代理運作狀態檢查也需要連線,因此,確保伺服器的工作集區足夠大,從而容納額外的運作狀態檢查請求非常重要。閑置工作程式很實惠,因此我們傾向於設定額外的工作程式:從少量額外工作程式到設定的代理最大連線數翻倍的任何方式。

我們用於對運作狀態檢查排列優先順序的另一種策略是,讓伺服器實作強制執行自己的最大並行請求。在這種情況下,始終允許負載平衡器運作狀態檢查,但如果伺服器已經在某個閾值上工作,則正常請求將被拒絕。Amazon 的實作範圍包括 Java 的簡單信號,到 CPU 利用率趨勢的更複雜分析。

有助於確保服務及時回應運作狀態檢查 ping 請求的另一種方法是,在後台執行緒中執行相依項運作狀態檢查邏輯,並更新 ping 邏輯檢查的 isHealthy 旗標。在這種情況下,伺服器會迅速回應運作狀態檢查,而相依項運作狀態檢查會在與之互動的外部系統上,產生可預測的負載。若團隊這樣做,他們在偵測到運作狀態檢查執行緒失敗時要格外謹慎。若該後台執行緒退出,則伺服器不會偵測到今後的伺服器失敗 (復原!)。

平衡相依項運作狀態檢查與影響範圍

相依項運作狀態檢查很有吸引力,因為它們可以對伺服器的運作狀態進行徹底的測試。可惜它們可能很危險,因為相依項可能導致整個系統出現串聯失敗。

透過研究 Amazon 的服務型體系結構,我們可以獲得有關處理運作狀態相依項的一些洞見。Amazon 的每項服務旨在做少量事情;沒有能完成所有任務的孤立大型單元。我們喜歡以這種方式來打造服務,原因有很多,其中包括小型團隊的創新速度更快,若一項服務存在問題,則影響範圍會減小。這種架構設計也可套用於運作狀態檢查。

當一項服務叫用另一項服務時,即依賴於該服務。若服務有時僅叫用相依項,則我們可能會將相依項視為「軟相依項」,因為即使服務無法與相依項進行通訊,該服務仍可執行某些類型的工作。若沒有失敗開啟保護,則實作測試相依項的運作狀態檢查會將其轉化為「硬相依項」。 若相依性下降,則服務也會下降,從而導致串聯失敗,影響範圍增大。

即使我們將功能分為不同的服務,每項服務也可能服務於多個 API。有時,服務上的 API 具有其自身的相依性。若一個 API 受到影響,我們希望該服務繼續提供其他 API。例如,服務既可以是控制平面 (如長期資源上有時也稱為 CRUD API),也可以是資料平面 (高輸送量業務超關鍵 API)。我們希望資料平面 API 能夠繼續運作,即使控制平面 API 在與其相依性交談時遇到問題。

同樣,視乎資料的輸入或狀態,即使是單一 API,其行為也可能有所差異。一種常見的模式是 Read API,其查詢資料庫,但會在本機快取回應一段時間。若資料庫已關閉,該服務仍可提供快取的讀取項,直至資料庫重新連線。若只有一個代碼路徑運作狀態不佳,則運作狀態檢查失敗會導致與相依項通訊時發生問題的影響範圍增大。

對運作狀態檢查具有哪種相依性的討論,提出下列相關問題,即微服務和相對單一服務之間的取捨。很少有明確的規則將服務劃分為多少個可部署單元或端點,但「運作狀態檢查具有哪些相依性」和「失敗後是否會增大影響範圍」的問題是有趣的鏡頭,可用於確定如何以微型或巨集來提供服務。 

運作狀態檢查發生問題的實際情況

從理論上講,所有這些都可以理解,但若系統沒有正確進行運作狀態檢查,那麼在實踐中該怎麼辦? 我們研究了 AWS 客戶和 Amazon 各地案例中的模式,以協助闡述更大的前景。我們還研究了補償因素,即團隊為了防止運作狀態檢查中的弱點引起廣泛問題,而實作的「帶式和吊帶式」分類。

部署

運作狀態檢查問題的其中一種模式涉及部署。AWS CodeDeploy 之類的部署系統可一次性將新代碼推送至機群的一個子集,等待一個部署浪潮完成,然後再進行下一個。此程序依賴於伺服器在啟動並使用新代碼執行後,再向部署系統報告。若不報告,則部署系統會發現新代碼存在問題,並復原部署。

最基本的服務啟動部署指令碼會簡單地分支伺服器程序,並立即回應「已完成部署」至部署系統。然而,這樣做很危險,因為新代碼可能會出錯︰新代碼可能在啟動後立即崩潰,出現掛斷,無法開始偵聽伺服器通訊端,無法載入成功處理請求所需的組態,或遇到錯誤。若部署系統沒有設定為針對相依項運作狀態檢查進行測試,則不會意識到其在推動不良部署。它會沿著破壞一部又一部伺服器的方式前進。

幸運的是,在實踐中,Amazon 團隊實作了多種緩解系統,以免這種情況耗盡整個機群。一種這樣的緩解措施是設定警報,這些警報將在總體機群規模太小,或在高負載下執行,或在出現高延遲或錯誤率時觸發。若觸發了任意一個警報,則部署系統會停止部署並復原。

緩解的另一種類型是使用分階段部署。服務可以設定為在暫停並針對該區域執行全套整合測試之前部署子集,可能是一個可用區域,而不是將整個機群部署在單一部署中。這種按可用區域部署的對齊方式非常方便,因為服務已設計為能夠在單一可用區域出現問題時保持運作。

當然,在部署至生產環境之前,Amazon 團隊會透過測試環境來推送這些變更,並執行自動整合測試,從而發現此類失敗。然而,生產環境和測試環境之間可能存在細微且不可避免的差異,因此,在對生產造成影響之前,務必結合多層部署安全性以發現各種問題。運作狀態檢查對於保護服務免受不良部署影響很重要,同時還要確保不要止步於此。我們考慮使用「帶式和吊帶式」方法作為後障,保護機群免受這些錯誤和其他錯誤的影響。

異步處理器

另一種失敗模式圍繞異步訊息處理,例如,透過輪詢 SQS 佇列或 Amazon Kinesis Stream 來獲得其工作的服務。與從負載平衡器接收請求的系統不同,這裡不會自動執行運作狀態檢查來將伺服器從服務中移除。

若服務沒有進行足夠的運作狀態檢查,則個別佇列工作伺服器可能出現磁碟填滿,或檔案描述元用盡等錯誤。該問題不會阻止伺服器將工作從佇列中拉出,但會阻止伺服器成功處理訊息。該問題會導致訊息處理延遲,其中錯誤的伺服器會迅速將工作從佇列中拉出,從而無法對其進行處理。

在這類情況下,通常會有幾種補償因素來協助控制影響。例如,若伺服器無法處理其從 SQS 發出的訊息,則在設定的訊息可視性逾時之後,SQS 會將該訊息重新傳送至另一部伺服器。端對端延遲增加,但訊息不會被丟棄。另一個補償因素是警報,若處理訊息的錯誤太多,則會發出警報,提醒操作人員進行調查。

磁碟填滿

我們看到的另一類失敗是,伺服器上的磁碟填滿時,導致處理和日誌記錄均失敗。由於伺服器可能無法將其失敗報告給監控系統,因此,該失敗會導致監控可視性出現差距。

同樣,一些緩解措施可以防止服務「盲目運作」,並迅速減輕影響。對於以 Application Load Balancer 或 API 閘道等代理作為前端的系統,具有該代理產生的錯誤率和延遲指標。在這種情況下,即使伺服器未報告,也會觸發警報。對於基於佇列的系統,Amazon Simple Queue Service (Amazon SQS) 之類的服務會報告指標,指示某些訊息的處理已延遲。

這些解決方案的共同點是存在多層監控。伺服器本身報告錯誤,而外部系統也報告錯誤。同樣的原則對運作狀態很重要。相較於測試自身,外部系統可以更準確地測試給定系統的運作狀態。藉助 AWS Auto Scaling,團隊可設定負載平衡器來執行外部 ping 運作狀態檢查,原因就在於此。

此外,團隊還可編寫自己的自訂運作狀態檢查系統,以定期詢問每部伺服器運作狀態是否良好,並在伺服器運作狀態不佳時向 AWS Auto Scaling 報告。該系統的一種常見實作方式是,每分鐘執行一次 Lambda 函數,測試每部伺服器的運作狀態。這些運作狀態檢查甚至可以將每次執行之間的狀態儲存在 DynamoDB 之類的位置,這樣它們就不會立即將過多的伺服器標記為運作狀態不佳。

僵屍

另一類問題包括殭屍伺服器。伺服器可能會在一段時間內與網路斷開連線,但仍保持執行狀態,或者可能長時間關閉電源並隨後重新啟動。

當殭屍伺服器恢復工作時,它們可能與其他機群顯著不同步,這可能會導致嚴重的問題。例如,若殭屍伺服器執行的是非常舊的、不相容的軟體版本,則當它嘗試與具有不同架構的資料庫進行互動時,可能會導致失敗或使用錯誤的組態。

若要處理殭屍,系統通常會使用其目前正在執行的軟體版本,來回覆運作狀態檢查。然後,中央監控代理程式會比較整個機群的回應,以尋找執行非預期過時版本的任何內容,並阻止這些伺服器重新投入使用。

結論

伺服器及其上執行的軟體因各種奇怪的原因而失敗。硬體最終會在實體上損壞。作為軟體開發人員,我們最終會編寫一些錯誤,例如我上面所述的錯誤,該錯誤會使軟體進入崩潰狀態。從輕量級活躍度檢查到被動監控每部伺服器的指標,需要多層檢查,以發現所有類型的非預期失敗模式。

當發生這些失敗時,重要的是要偵測到這些失敗,並使受影響的伺服器快速退出服務。然而,與任何機群自動化一樣,我們新增了限速、閾值和斷路器,這會關閉自動化,並在不確定或極端情況下使人員介入。失敗開啟和建立集中式動作項目,是對限速自動化安全性進行深度運作狀態檢查並從中獲益的策略。

實作實驗室

試用您在此從實作實驗室學到的部分原則。


作者簡介

David Yanacek 是 AWS Lambda 的資深首席工程師。自 2006 年以來,David 一直擔任 Amazon 的軟體開發人員,之前負責 Amazon DynamoDB 和 AWS IoT、內部 Web 服務框架,以及車隊營運自動化系統的開發。David 工作中最喜歡的活動之一是,執行日誌分析並篩選操作指標,以尋找讓系統隨時間推移而執行越來越平穩的方法。

採用抖動的逾時、重試和退避