本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
最佳化 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 佇列深度和網路輸送量。您可以使用 CloudWatch Container Insights 等服務收集這些指標。您也可以使用 Amazon Managed Service for Prometheus 搭配 Amazon Managed Grafana 來收集它們。在此過程中,請確定您收集並繪製應用程式回應時間或工作完成率的指標。
當您載入測試時,請從小請求或任務插入率開始。將此速率保持穩定幾分鐘,讓您的應用程式暖機。然後,緩慢提高速率並保持穩定幾分鐘。重複此週期,每次增加速率,直到應用程式的回應或完成時間太慢而無法滿足您的服務水準目標 (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 容量,請考慮將其放置在運算最佳化的執行個體上,例如 c5
或 c6g
系列。
有效率的記憶體繫結伺服器
有效率的記憶體繫結伺服器會為每個請求配置大量記憶體。在並行上限,但不一定是輸送量時,記憶體會在 CPU 資源耗盡之前耗盡。與請求相關聯的記憶體會在請求結束時釋放。只要有可用的記憶體,就可以接受其他請求。
您可以針對此類型的應用程式使用記憶體型自動擴展。應用程式在擴展方面享有最大的彈性。您可以透過提供較大的 Amazon EC2 或 Fargate 記憶體資源來垂直擴展。此外,您也可以新增更多複本來水平擴展。新增更多複本或將執行個體大小加倍,可以將相對於容量的平均記憶體使用率減少一半。
如果您為此應用程式使用 Amazon EC2 容量,請考慮將其放置在記憶體最佳化的執行個體上,例如 r5
或 r6g
系列。
有些記憶體繫結應用程式不會在請求結束時釋放與請求相關聯的記憶體,因此減少並行不會導致使用的記憶體減少。因此,我們不建議您使用記憶體型擴展。
工作者型伺服器
工作者型伺服器會逐一處理每個個別工作者執行緒的請求。工作者執行緒可以是輕量型執行緒,例如 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
指標。使用此指標進行擴展之前,應先在所有消費者之間進行平均。