本文提供容器化 Java 應用程式的建議策略和設定概觀。 當你將 Java 應用程式容器化時,請仔細考慮容器可用的 CPU 時間。 接著考慮可用記憶體的總量與 Java 虛擬機(JVM)堆積大小。 在容器化環境中,應用程式可能會存取所有處理器,因此能夠平行執行多個線程。 不過,容器通常會被設定CPU配額,這可能會限制對CPU的存取。
JVM 利用啟發式方法根據 CPU 配額來判斷「可用處理器」數量,這會大幅影響 Java 應用程式的效能。 配置給容器本身的記憶體,以及 JVM 堆積區域的大小與處理器一樣重要。 這些因素會決定垃圾回收器(GC)的運作方式,以及系統的整體效能。
小提示
如果你不想手動調整這些設定,Azure 的 Javajaz 指令啟動器()會自動套用雲端原生的 JVM 預設值。 它是 java 指令的可直接替代方案,能偵測容器限制並選擇最合適的堆積大小與 GC 旗標。 欲了解更多資訊,請參閱「用Azure指令啟動器自動調校JVM」Java。
容器化新的應用程式
當你為新應用程式容器化 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 會為系統中可用 RAM 最多為 256 MB 的系統設定預設的 最大 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 核心;或者在 Kubernetes 上執行 2000m 時,至少使用 cpu_limit。 容器化環境中不要選擇少於一個 vCPU 核心。
小提示
如果您不知道要從多少核心開始,則不錯的選擇是兩個 vCPU 核心。
挑選起點
先從 Kubernetes、OpenShift、Azure Spring 應用程式、Azure 容器應用程式 和 Azure App 服務 等容器協調環境中的兩個複本或執行個體開始。 下表摘要說明新 Java 應用程式容器化的建議起點。
| vCPU 核心 | 容器記憶體 | JVM 堆儲存空間大小 | GC | 複製品 |
|---|---|---|---|---|
| 2 | 4 GB | 75% | ParallelGC | 2 |
使用下列 JVM 參數:
-XX:+UseParallelGC -XX:MaxRAMPercentage=75
使用 Azure Command Launcher for Java 自動調校 JVM
前述章節說明如何根據你的容器記憶體、CPU 核心和工作負載類型手動選擇 JVM 旗標。 如果你不想自己維護這些設定,Azure Javajaz 指令啟動器會自動套用雲端原生的 JVM 預設值。
Azure Java 指令啟動器是一個輕量級的工具,位於你的啟動指令和 JVM 之間。 它偵測雲端環境,包括容器記憶體與 CPU 限制,並選擇最佳調整旗標以進行堆積大小、GC 選擇及診斷。 此方法降低設定負擔並提升資源利用率,開箱即用。
若要使用此工具,請在啟動指令碼或 Dockerfile 中,以 jaz 取代 java 命令。 例如,與其手動調整 JVM 選項:
java -XX:+UseParallelGC -XX:MaxRAMPercentage=75 -jar myapp.jar
使用 jaz:
jaz -jar myapp.jar
此工具包含在 Microsoft Build of OpenJDK 的容器映像中,因此不需要額外的設定。 以下 Dockerfile 使用 jaz 從 jar 檔案執行 Java 應用程式:
# Use any Microsoft Build of OpenJDK base image
FROM mcr.microsoft.com/openjdk/jdk:25-ubuntu
# Add your application.jar
COPY application.jar /application.jar
# Use jaz to launch your Java application
CMD ["jaz", "-jar", "application.jar"]
關於安裝選項、支援環境及設定細節,請參見 Azure 命令啟動器 for Java。
容器化現有的本地部署應用程式
如果您的應用程式已經在本地或雲端的虛擬機上運行,請從以下設定開始:
- 應用程式目前可存取的記憶體數量相同。
- 目前應用程式可用的 CPU 或 vCPU 核心數目相同。
- 您目前使用的相同 JVM 參數。
如果 vCPU 核心或容器記憶體組合無法取得,就選擇最近的一個,將 vCPU 核心和容器記憶體四捨五入。
後續步驟
現在你已經了解了 Java 應用程式容器化的一般建議,請繼續閱讀以下文章,建立容器化基線並簡化 JVM 的調整: