本文提供容器化 Java 應用程式的建議策略和設定概觀。 當您將 Java 應用程式容器化時,請仔細考慮容器可用的 CPU 時間。 然後,請考慮在記憶體總量和 Java 虛擬機 (JVM) 的堆積大小方面,可以使用多少記憶體。 在容器化環境中,應用程式可能會存取所有處理器,因此能夠平行執行多個線程。 不過,容器通常會被設定CPU配額,這可能會限制對CPU的存取。
JVM 有啟發學習法,可根據 CPU 配額來判斷「可用的處理器」數目,這可能會大幅影響 Java 應用程式的效能。 配置給容器本身的記憶體,以及 JVM 堆積區域的大小與處理器一樣重要。 這些因素會決定垃圾回收器(GC)的運作方式,以及系統的整體效能。
容器化新的應用程式
當您為新的應用程式容器化 Java 工作負載時,在考慮記憶體時,必須考慮兩件事:
- 配置給容器本身的記憶體。
- Java 進程可用的記憶體數量。
瞭解 JVM 預設調整參數
應用程式需要起點和設定。 JVM 具有以可用處理器數目和系統中記憶體數量為基礎的預先定義值的預設程式設計工具。 當 JVM 啟動時,不使用特定的啟動旗標或參數,就會使用下表中顯示的預設值。
下表顯示用於可用資源的預設 GC:
可用的資源 | 預設 GC |
---|---|
任意數目的處理器 最多 1,791 MB 的記憶體 |
SerialGC |
2 個以上的處理器 1,792 MB 以上的記憶體 |
G1GC |
下表顯示預設的最大堆積大小,視 JVM 執行所在的環境中可用的記憶體數量而定:
可用的記憶體 | 預設堆積大小上限 |
---|---|
最多 256 MB | 可用記憶體位址 50% |
256 MB 到 512 MB | ~127 MB |
超過 512 MB | 可用記憶體的 25%% |
預設的初始堆積大小是可用記憶體的 1/64。 這些值適用於 OpenJDK 11 及更高版本,並適用於大多數版本,包括 Microsoft OpenJDK 構建、Azul Zulu、Eclipse Temurin、Oracle OpenJDK 等。
判斷容器記憶體
根據應用程式的需求及其獨特的使用模式,挑選最適合您工作負載的容器記憶體數量。 例如,如果您的應用程式建立大型物件圖形,則可能需要比具有許多小型物件圖形的應用程式所需的記憶體還要多。
小提示
如果您不知道要配置多少記憶體,良好的起點是 4 GB。
判斷 JVM 堆積記憶體
當您配置 JVM 堆積記憶體時,JVM 需要比 JVM 堆積所使用的記憶體更多。 當您設定 JVM 堆積記憶體上限時,不應該等於容器記憶體的數量,因為這會導致容器記憶體不足(OOM)錯誤和容器當機。
小提示
分配 75% 的容器記憶體給 JVM 堆。
在 OpenJDK 11 和更新版本上,您可以透過下列方式設定 JVM 堆積大小:
說明 | 旗標 | 範例 |
---|---|---|
固定值 | -Xmx |
-Xmx4g |
動態值 | -XX:MaxRAMPercentage |
-XX:MaxRAMPercentage=75 |
最小/初始堆積大小
如果環境保證保留給 JVM 實例的特定內存量,例如在容器中,您應該將堆積大小下限或初始堆積大小設定為與堆積大小上限相同的大小。 此設定會向 JVM 指出它不應該執行將記憶體釋放至 OS 的工作。
若要設定最小堆積大小,請使用 -Xms
絕對數量或 -XX:InitialRAMPercentage
百分比數量。
這很重要
旗標 -XX:MinRAMPercentage
,雖然名稱可能讓人有不同聯想,但實際上是用來為擁有多達 256 MB RAM 的系統設定預設 RAM 百分比的上限。
判斷要使用的 GC
先前,您已決定要開始使用的 JVM 堆積記憶體數量。 下一個步驟是選擇您的總承包商 (GC)。 您擁有的最大 JVM 堆積記憶體數量通常是選擇 GC 的因素。 下表描述每個 GC 的特性。
因素 | SerialGC | ParallelGC | G1GC | ZGC | 謝南多亞GC |
---|---|---|---|---|---|
核心數目 | 1 | 2 | 2 | 2 | 2 |
多線程 | 否 | 是的 | 是的 | 是的 | 是的 |
Java 堆大小 | <4 GB | <4 GB | >4 GB | >4 GB | >4 GB |
暫停 | 是的 | 是的 | 是的 | 是 (<1 毫秒) | 是 (<10 毫秒) |
額外負荷 | 極小 | 極小 | 溫和 | 溫和 | 溫和 |
尾延遲效應 | 高 | 高 | 高 | 低 | 溫和 |
JDK 版本 | 全部 | 全部 | JDK 8+ | JDK 17+ | JDK 11+ |
最適合使用於 | 單核心小型堆 | 具有任何堆積大小的多核心小型堆積或批次工作負載 | 在中型到大型資料批處理中響應(請求-回應/資料庫互動) | 在中型到大型資料批處理中響應(請求-回應/資料庫互動) | 在中型到大型資料批處理中響應(請求-回應/資料庫互動) |
小提示
針對大部分一般用途的微服務應用程式,請從平行 GC 開始。
判斷需要多少 CPU 核心
針對 SerialGC 以外的任何 GC,我們建議使用兩個以上的 vCPU 核心,或至少 2000m
適用於 cpu_limit
Kubernetes。 我們不建議在容器化環境中選擇小於一個 vCPU 核心的任何配置。
小提示
如果您不知道要從多少核心開始,則不錯的選擇是兩個 vCPU 核心。
挑選起點
建議您從 Kubernetes、OpenShift、Azure Spring Apps、Azure Container Apps 和 Azure App Service 等容器協調流程環境中的兩個複本或實例開始。 下表摘要說明新 Java 應用程式容器化的建議起點。
vCPU 核心 | 容器記憶體 | JVM 堆儲存空間大小 | GC | 複製品 |
---|---|---|---|---|
2 | 4 GB | 75% | ParallelGC | 2 |
使用下列 JVM 參數:
-XX:+UseParallelGC -XX:MaxRAMPercentage=75
容器化現有的內部部署應用程式
如果您的應用程式已在內部部署或雲端中的 VM 上執行,建議您從下列組態開始:
- 應用程式目前可存取的記憶體數量相同。
- 目前應用程式可用的 CPU 或 vCPU 核心數目相同。
- 您目前使用的相同 JVM 參數。
如果 vCPU 核心或容器記憶體的組合無法使用,請挑選最接近的組合,並將 vCPU 核心和容器記憶體向上取整。
後續步驟
既然您已瞭解容器化 Java 應用程式的一般建議,請繼續進行下列文章,以建立容器化基準: