最佳化 Amazon ECS 服務自動擴展 - Amazon Elastic Container Service

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

最佳化 Amazon ECS 服務自動擴展

Amazon ECS 服務是受管任務集合。每個服務都有相關聯的任務定義、所需的任務計數,以及選用的置放策略。Amazon ECS 服務自動擴展是透過 Application Auto Scaling 服務實作。Application Auto Scaling 使用 CloudWatch 指標作為擴展指標的來源。它也會使用 CloudWatch 警示來設定何時縮減或縮減服務的閾值。您可以透過設定指標目標、稱為目標追蹤擴展或指定閾值來提供擴展的閾值,稱為步驟擴展。設定 Application Auto Scaling 之後,它會持續計算服務的適當所需任務計數。它也會透過向外擴展或向內擴展來通知 Amazon ECS 所需的任務計數何時變更。

若要有效使用服務自動擴展,您必須選擇適當的擴展指標。

如果預測需求大於目前容量,應用程式應橫向擴展。相反地,應用程式可以縮減規模,以便在資源超過需求時節省成本。

識別指標

若要有效擴展,請務必識別表示使用率或飽和度的指標。此指標必須顯示下列屬性,才有助於擴展。

  • 指標必須與需求相關聯。當資源保持穩定,但需求變更時,指標值也必須變更。當需求增加或減少時,指標應該增加或減少。

  • 指標值必須按比例擴展至容量。當需求保持不變時,新增更多資源必須在指標值中產生比例變更。因此,將任務數量加倍應該會導致指標減少 50%。

識別使用率指標的最佳方法是透過生產前環境中的負載測試,例如預備環境。商業和開放原始碼負載測試解決方案已廣泛推出。這些解決方案通常可以產生合成負載或模擬實際使用者流量。

若要開始負載測試程序,請為應用程式的使用率指標建置儀表板。這些指標包括 CPU 使用率、記憶體使用率、I/O 操作、I/O 佇列深度和網路輸送量。您可以使用 Container Insights 等服務收集這些指標。如需詳細資訊,請參閱使用具有增強可觀測性的 Container Insights 監控 Amazon ECS 容器。在此過程中,請確定您收集並繪製應用程式回應時間或工作完成率的指標。

從小請求或任務插入率開始。將此速率保持穩定幾分鐘,讓您的應用程式暖機。然後,緩慢提高速率並保持穩定幾分鐘。重複此週期,每次增加速率,直到應用程式的回應或完成時間太慢而無法滿足您的服務水準目標 (SLOs)。

在負載測試時,檢查每個使用率指標。隨負載增加的指標是做為最佳使用率指標的最佳候選者。

接著,識別達到飽和的資源。同時,也請檢查使用率指標,以查看哪個指標先在高層級水平化,或達到峰值,然後先當機您的應用程式。例如,如果您在新增負載時,CPU 使用率從 0% 增加到 70-80%,則在新增更多負載之後, 會保持在該層級,那麼可以放心地說 CPU 已飽和。根據 CPU 架構,它可能永遠不會達到 100%。例如,假設記憶體使用率隨著您新增負載而增加,然後您的應用程式會在達到任務或 Amazon EC2 執行個體記憶體限制時突然當機。在這種情況下,記憶體可能已完全耗盡。您的應用程式可能會耗用多個資源。因此,請選擇代表先耗盡資源的指標。

最後,將任務或 Amazon EC2 執行個體數量加倍後,再次嘗試載入測試。假設索引鍵指標以以前的一半速率增加或減少。如果是這種情況,則指標與容量成正比。這是自動擴展的良好使用率指標。

現在請考量這個假設案例。假設您載入測試應用程式,並發現 CPU 使用率最終達到每秒 100 個請求的 80%。新增更多負載時,不會再增加 CPU 使用率。不過,它確實會讓您的應用程式回應速度變慢。然後,您再次執行負載測試,將任務數量加倍,但將速率保持在先前的峰值。如果您發現平均 CPU 使用率下降到約 40%,則平均 CPU 使用率是擴展指標的理想候選項目。另一方面,如果 CPU 使用率在增加任務數量後仍維持在 80%,則平均 CPU 使用率不是良好的擴展指標。在這種情況下,需要更多研究才能找到合適的指標。

常見的應用程式模型和擴展屬性

所有類型的軟體都會在 上執行 AWS。許多工作負載都是自製的,而其他工作負載則是以熱門的開放原始碼軟體為基礎。無論它們源自何處,我們觀察到一些常見的 服務設計模式。如何有效擴展在很大程度上取決於模式。

有效率的 CPU 繫結伺服器

有效率的 CPU 繫結伺服器幾乎不使用 CPU 和網路輸送量以外的資源。每個請求都可以由應用程式單獨處理。請求不依賴其他 服務,例如資料庫。應用程式可以處理數十萬個並行請求,並且可以有效地利用多個 CPUs來執行此操作。每個請求都由記憶體負荷低的專用執行緒提供服務,或者有一個非同步事件迴圈在服務請求的每個 CPU 上執行。應用程式的每個複本都同樣能夠處理請求。在 CPU 之前可能耗盡的唯一資源是網路頻寬。在 CPU 繫結服務中,即使是尖峰輸送量,記憶體使用率也是可用資源的一小部分。

這種類型的應用程式適用於以 CPU 為基礎的自動擴展。應用程式在擴展方面享有最大的彈性。它可以透過提供較大的 Amazon EC2 執行個體或 Fargate vCPUs來垂直擴展。而且,它也可以透過新增更多複本來水平擴展。新增更多複本,或將執行個體大小加倍, 會將相對於容量的平均 CPU 使用率減少一半。

如果您為此應用程式使用 Amazon EC2 容量,請考慮將其放置在運算最佳化的執行個體上,例如 c5c6g 系列。

有效率的記憶體繫結伺服器

有效率的記憶體繫結伺服器會為每個請求配置大量記憶體。在並行上限,但不一定是輸送量時,記憶體會在 CPU 資源耗盡之前耗盡。與請求相關聯的記憶體會在請求結束時釋放。只要有可用的記憶體,就可以接受其他請求。

這種類型的應用程式適用於記憶體型自動擴展。應用程式在擴展方面享有最大的彈性。它可以透過提供較大的 Amazon EC2 或 Fargate 記憶體資源來垂直擴展。而且,它也可以透過新增更多複本來水平擴展。新增更多複本或將執行個體大小加倍,可將相對於容量的平均記憶體使用率減少一半。

如果您為此應用程式使用 Amazon EC2 容量,請考慮將其放在記憶體最佳化的執行個體上,例如 r5r6g 系列。

有些記憶體繫結應用程式不會在請求結束時釋放與請求相關聯的記憶體,因此減少並行不會導致使用的記憶體減少。因此,我們不建議您使用記憶體型擴展。

工作者型伺服器

工作者型伺服器會逐一處理每個個別工作者執行緒的請求。工作者執行緒可以是輕量型執行緒,例如 POSIX 執行緒。它們也可以是更重的執行緒,例如 UNIX 程序。無論它們是哪個執行緒,永遠都有應用程式可支援的並行上限。通常,並行限制會與可用的記憶體資源成比例設定。如果達到並行限制,其他請求會放置在待處理項目佇列中。如果待處理項目佇列溢位,則會立即拒絕其他傳入的請求。符合此模式的常見應用程式包括 Apache Web 伺服器和 Gunicorn。

請求並行通常是擴展此應用程式的最佳指標。由於每個複本都有並行限制,因此請務必在達到平均限制之前向外擴展。

取得請求並行指標的最佳方法是讓您的應用程式向 CloudWatch 報告。您應用程式的每個複本都可以以高頻率將並行請求的數量發佈為自訂指標。我們建議將頻率設定為至少每分鐘一次。收集多個報告之後,您可以使用平均並行做為擴展指標。此指標的計算方式是將總並行數除以複本數量。例如,如果並行總數為 1000,而複本數量為 10,則平均並行數為 100。

如果您的應用程式位於 Application Load Balancer 後方,您也可以使用負載平衡器的 ActiveConnectionCount指標做為擴展指標的因素。ActiveConnectionCount 指標必須除以複本數量,才能取得平均值。平均值必須用於擴展,而不是原始計數值。

為了讓此設計發揮最佳效能,回應延遲的標準偏差應該在低請求率下很小。我們建議在低需求期間,大多數請求會在短時間內得到回應,而且沒有比平均回應時間更長的許多請求。平均回應時間應接近第 95 個百分位數的回應時間。否則,佇列溢位可能會因此發生。這會導致錯誤。我們建議您在必要時提供額外的複本,以降低溢位的風險。

等待伺服器

等待伺服器會為每個請求進行一些處理,但高度依賴一或多個下游服務來運作。容器應用程式通常會大量使用下游服務,例如資料庫和其他 API 服務。這些服務可能需要一些時間才能回應,特別是在高容量或高並行情況下。這是因為這些應用程式傾向於使用少量 CPU 資源,並根據可用的記憶體利用其最大並行。

等待服務適合記憶體繫結伺服器模式或工作者型伺服器模式,視應用程式的設計方式而定。如果應用程式的並行僅受限於記憶體,則應使用平均記憶體使用率做為擴展指標。如果應用程式的並行是根據工作者限制,則應使用平均並行做為擴展指標。

Java 型伺服器

如果您的 Java 型伺服器是 CPU 繫結型伺服器,並依 CPU 資源比例擴展,則可能適合有效率的 CPU 繫結型伺服器模式。如果是這種情況,平均 CPU 使用率可能適合做為擴展指標。不過,許多 Java 應用程式不受 CPU 限制,因此難以擴展。

為了獲得最佳效能,建議您盡可能將記憶體配置給 Java 虛擬機器 (JVM) 堆積。最近的 JVM 版本,包括 Java 8 更新 191 或更新版本,會自動將堆積大小設定為盡可能大,以符合容器。這表示在 Java 中,記憶體使用率很少與應用程式使用率成正比。隨著請求率和並行增加,記憶體使用率保持不變。因此,我們不建議根據記憶體使用率擴展以 Java 為基礎的伺服器。反之,我們通常會建議擴展 CPU 使用率。

在某些情況下,Java 型伺服器會在耗盡 CPU 之前遇到堆積耗盡。如果您的應用程式容易在高並行情況下堆積耗盡,則平均連線是最佳擴展指標。如果您的應用程式容易以高輸送量堆積耗盡,則平均請求率是最佳擴展指標。

使用其他垃圾收集執行時間的伺服器

許多伺服器應用程式是以執行垃圾收集的執行時間為基礎,例如 .NET 和 Ruby。這些伺服器應用程式可能符合先前所述的其中一種模式。不過,與 Java 一樣,我們不建議根據記憶體擴展這些應用程式,因為他們觀察到的平均記憶體使用率通常與輸送量或並行無關。

對於這些應用程式,如果應用程式受限於 CPU,我們建議您擴展 CPU 使用率。否則,我們建議您根據您的負載測試結果,擴展平均輸送量或平均並行。

任務處理器

許多工作負載涉及非同步任務處理。其中包括未即時接收請求的應用程式,而是訂閱工作佇列以接收工作。對於這些類型的應用程式,適當的擴展指標幾乎一律是佇列深度。佇列成長表示待定的工作超出處理容量,而空佇列表示容量比工作多。

AWS 訊息服務,例如 Amazon SQS 和 Amazon Kinesis Data Streams,提供可用於擴展的 CloudWatch 指標。對於 Amazon SQS, ApproximateNumberOfMessagesVisible是最佳指標。對於 Kinesis Data Streams,請考慮使用 Kinesis Client Library (KCL) 發佈的 MillisBehindLatest 指標。使用此指標進行擴展之前,應先在所有消費者之間進行平均。