設定服務自動擴展 - Amazon Elastic Container Service

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

設定服務自動擴展

Amazon ECS 服務是任務的受管集合。每個服務都有相關的任務定義、所需的任務計數,以及選擇性的放置策略。Amazon ECS 服務自動擴展是透過 Application Auto Scaling 服務實作的。Application Auto Scaling 會使用 CloudWatch 度量做為調整度量的來源。它也會使用 CloudWatch 警示來設定何時向內或向外擴展服務的臨界值。您可以透過設定測量結果目標 (稱為目標追蹤擴展,或藉由指定臨界值 (稱為步驟擴展。設定「Application Auto Scaling 比例」之後,它會持續計算服務所需的適當工作計數。它也會在需要的任務計數應該變更時通知 Amazon ECS,方法是向外擴展或擴展。

若要有效地使用服務自動調整,您必須選擇適當的調整度量。我們在下節討論如何選擇指標。

描述您的應用程式

正確擴展應用程序需要知道應該擴展應用程序的條件,以及何時應該擴展應用程序。基本上,如果預測需求超出容量,應該向外擴充應用程式。相反地,應用程式可以在資源超過需求時進行調整,以節省成本。

識別使用率測量結果

若要有效擴充,識別指出使用率或飽和度的度量非常重要。此度量必須具有下列屬性,才能調整比例。

  • 測量結果必須與需求相關。當資源保持穩定,但需求變更時,測量結果值也必須變更。當需求增加或減少時,量度應該增加或減少。

  • 度量值必須按容量比例調整。當需求保持固定時,新增更多資源必須導致測量結果值的比例變更。因此,工作數目加倍應該會導致量度減少 50%。

識別使用率度量的最佳方式是透過預先生產環境 (例如臨時環境) 中的負載測試。商業和開放原始碼負載測試解決方案已廣泛提供。這些解決方案通常可以產生合成負載或模擬實際使用者流量。

若要開始負載測試的程序,您應該先為應用程式的使用率度量建置儀表板。這些度量包括 CPU 使用率、記憶體使用率、I/O 作業、I/O 佇列深度以及網路輸送量。您可以透過 CloudWatch 容器深入解析等服務收集這些指標。或者,通過使用 Prometheus 的亞馬遜託管服務以及格拉法納的亞馬遜託管服務來執行此操作。在此程序期間,請確定您收集並繪製應用程式回應時間或工作完成率的度量。

負載測試時,請從小量的請求或工作插入率開始。保持這個速率穩定數分鐘,以便您的應用程序熱身。然後, 慢慢地增加速率並保持穩定幾分鐘. 重複此週期,每次都會增加速率,直到應用程式的回應或完成時間太慢,無法滿足您的服務層級目標 (SLO) 為止。

負載測試時,請檢查每個使用率度量。隨著負載增加的度量是最佳使用率度量的最佳候選人。

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

最後,請在任務數量或 Amazon EC2 執行個體加倍後再次嘗試載入測試。假設關鍵度量增加或減少的速率與之前相同。如果是這種情況,則度量與容量成正比。這是一個很好的自動調整使用率度量。

現在考慮一下這個假設的情況。假設您載入測試應用程式,並發現 CPU 使用率最終達到 80%,每秒 100 個要求。當增加更多負載時,它不會使 CPU 使用率再提高。但是,它確實使您的應用程序響應更慢。然後,您再次執行負載測試,將工作數目加倍,但將速率保持在先前的尖峰值。如果您發現平均 CPU 使用率降至約 40%,則平均 CPU 使用率是調整量度的適當候選項。另一方面,如果增加工作數量後 CPU 使用率維持在 80%,則平均 CPU 使用率不是一個很好的縮放度量。在這種情況下,需要更多的研究來找到一個合適的指標。

一般應用程式模型和縮放屬性

各種軟件運行在AWS。許多工作負載都是本地生產,而其他工作負載則是以熱門的開放原始碼軟體為基礎 無論它們的起源在哪裡,我們都觀察到了一些常見的服務設計模式。如何有效地擴展取決於在很大程度上的模式。

高效率的 CPU 綁定伺服器

高效率的 CPU 繫結伺服器除了 CPU 和網路輸送量之外,幾乎不會使用任何資源。每個請求可以單獨由應用程序處理。請求不依賴於其他服務,如數據庫。該應用程序可以處理數十萬個並發請求,並且可以有效地利用多個 CPU 來執行此操作。每個要求是由具有低記憶體負荷的專用執行緒服務,或是有服務要求的每個 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 使用率。否則,我們建議您根據負載測試結果,依平均輸送量或平均並行量進行調整。

Job 處理器

許多工作負載涉及非同步工作處理。它們包括不會即時接收要求的應用程式,而是訂閱工作佇列以接收工作。對於這些類型的應用程式,適當的調整度量幾乎總是佇列深度。佇列成長表示待處理工作超出處理能力,而空白佇列表示有比工作要做更多的容量。

AWS傳訊服務 (例如 Amazon SQS 和 Amazon Kinesis Data Streams) 提供可用於擴展的 CloudWatch 指標。對於 Amazon SQS,ApproximateNumberOfMessagesVisible是最佳度量。對於 Kinesis Data Streams,請考慮使用MillisBehindLatest指標,由 Kinesis 用戶端程式庫 (KCL) 發行。此度量應該在所有取用者之間平均值,然後再將其用於調整。