Teilen über


Containerisieren Ihrer Java-Anwendungen

Dieser Artikel enthält eine Übersicht über empfohlene Strategien und Einstellungen für die Containerisierung von Java-Anwendungen. Berücksichtigen Sie beim Containerisieren einer Java-Anwendung sorgfältig, wie viel CPU-Zeit der Container verfügbar ist. Überlegen Sie dann, wie viel Arbeitsspeicher sowohl im Hinblick auf die Gesamtspeichermenge als auch die Heap-Größe des virtuellen Java-Computers (JVM) verfügbar ist. In containerisierten Umgebungen haben Anwendungen möglicherweise Zugriff auf alle Prozessoren und können daher mehrere Threads parallel ausführen. Es ist jedoch üblich, dass Container über ein CPU-Kontingent verfügen, das den Zugriff auf CPUs möglicherweise drosselt.

Die JVM verfügt über Heuristiken, um die Anzahl der "verfügbaren Prozessoren" basierend auf dem CPU-Kontingent zu bestimmen, was die Leistung von Java-Anwendungen erheblich beeinflussen kann. Der dem Container zugewiesene Speicher und die Größe des Heapbereichs für das JVM sind ebenso wichtig wie die Prozessoren. Diese Faktoren bestimmen das Verhalten des Garbage Collector (GC) und die Gesamtleistung des Systems.

Containerisieren einer neuen Anwendung

Wenn Sie eine Java-Arbeitslast für eine neue Anwendung containerisieren, müssen Sie zwei Dinge berücksichtigen, wenn Sie den Arbeitsspeicher betrachten:

  • Der dem Container zugeordnete Speicher selbst.
  • Die Für den Java-Prozess verfügbare Arbeitsspeichermenge.

Grundlegendes zu JVM-Standard-Ergonomie

Anwendungen benötigen einen Ausgangspunkt und Einstellungen. Das JVM verfügt über Standard-Ergonomie mit vordefinierten Werten, die auf der Anzahl der verfügbaren Prozessoren und der Menge des Arbeitsspeichers im System basieren. Die in den folgenden Tabellen gezeigten Standardwerte werden verwendet, wenn das JVM ohne bestimmte Startflags oder Parameter gestartet wird.

Die folgende Tabelle zeigt die Standard-GC, die für die verfügbaren Ressourcen verwendet wird:

Verfügbare Ressourcen Standard-GC
Beliebige Anzahl von Prozessoren
Bis zu 1.791 MB Arbeitsspeicher
SerialGC
2+ Prozessoren
1.792 MB oder mehr Arbeitsspeicher
G1GC

Die folgende Tabelle zeigt die standardmäßige maximale Heap-Größe, je nachdem, wie viel Arbeitsspeicher in der Umgebung verfügbar ist, in der der JVM ausgeführt wird:

Verfügbarer Arbeitsspeicher Standardmäßige maximale Heapgröße
Bis zu 256 MB 50 % des verfügbaren Speichers
256 MB bis 512 MB ~127 MB
Mehr als 512 MB 25 % des verfügbaren Speichers

Die standardmäßige anfängliche Heapgröße beträgt 1/64 des verfügbaren Arbeitsspeichers. Diese Werte gelten für OpenJDK 11 und höher und für die meisten Verteilungen, einschließlich Microsoft Build of OpenJDK, Azul Zulu, Eclipse Temurin, Oracle OpenJDK und anderen.

Speicher des Containers bestimmen

Wählen Sie einen Containerspeicherbetrag aus, der Ihrer Arbeitslast am besten entspricht, abhängig von den Anforderungen Ihrer Anwendung und ihren unverwechselbaren Verwendungsmustern. Wenn Ihre Anwendung beispielsweise große Objektdiagramme erstellt, benötigen Sie wahrscheinlich mehr Arbeitsspeicher als für Anwendungen mit vielen kleinen Objektdiagrammen.

Tipp

Wenn Sie nicht wissen, wie viel Arbeitsspeicher zugewiesen werden soll, ist ein guter Ausgangspunkt 4 GB.

JVM Heap-Speicher bestimmen

Wenn Sie JVM Heap-Speicher zuweisen, benötigt die JVM mehr Speicher als für den JVM Heap verwendet wird. Wenn Sie den maximalen JVM-Heapspeicher festlegen, sollte er niemals der Menge des Containerspeichers entsprechen, da dadurch Fehler im Container außerhalb des Arbeitsspeichers (Out of Memory, OOM) und Containerabstürzen verursacht werden.

Tipp

Weisen Sie 75% des Containerspeichers für den JVM Heap zu.

Auf OpenJDK 11 und höher können Sie die JVM-Heapgröße auf folgende Weise festlegen:

BESCHREIBUNG Flagge Beispiele
Fester Wert -Xmx -Xmx4g
Dynamischer Wert -XX:MaxRAMPercentage -XX:MaxRAMPercentage=75

Minimale/anfängliche Heap-Größe

Wenn die Umgebung garantiert einen bestimmten Speicherplatz für eine JVM-Instanz reserviert hat, z. B. in einem Container, sollten Sie die minimale Heap-Größe ( oder die anfängliche Heap-Größe ) auf dieselbe Größe wie die maximale Heapgröße festlegen. Diese Einstellung gibt dem JVM an, dass er nicht die Aufgabe ausführen sollte, Arbeitsspeicher auf das Betriebssystem freizugeben.

Um eine Mindestgröße für den Heap festzulegen, verwenden Sie -Xms für absolute Werte oder -XX:InitialRAMPercentage für prozentuale Werte.

Von Bedeutung

Das Kennzeichen -XX:MinRAMPercentagewird trotz des Namens verwendet, um den standardmäßigen maximalen RAM-Prozentsatz für Systeme mit bis zu 256 MB RAM festzulegen, der im System verfügbar ist.

Diagramm mit der Standard-Heap-Größe in OpenJDK 17.

Bestimmen, welcher GC verwendet werden soll

Zuvor haben Sie die Menge an JVM Heap-Speicher festgelegt, mit der Sie beginnen möchten. Der nächste Schritt ist die Auswahl Ihres GC. Die Größe des maximalen JVM Heap-Speichers, über den Sie verfügen, ist oft ein Faktor bei der Wahl Ihres GC. In der folgenden Tabelle werden die Merkmale der einzelnen GC beschrieben.

Faktoren SerialGC ParallelGC G1GC ZGC ShenandoahGC
Anzahl von Kernen 1 2 2 2 2
Multithreading Nein Ja Ja Ja Ja
Java Heap-Größe <4 GByte <4 GByte >4 GByte >4 GByte >4 GByte
Anhalten Ja Ja Ja Ja (<1 ms) Ja (<10 ms)
Mehraufwand Wenig Wenig Mäßig Mäßig Mäßig
Tail-Latency-Effekt Hoch Hoch Hoch Niedrig Mäßig
JDK-Version Alle Alle JDK 8+ JDK 17+ JDK 11+
Am besten geeignet für: Kleine Heaps für einen Kern Multi-Core kleine Heaps oder Batch Workloads mit beliebiger Heap-Größe Responsive in mittleren bis großen Heaps (Anfrage-Antwort/DB-Interaktionen) Responsive in mittleren bis großen Heaps (Anfrage-Antwort/DB-Interaktionen) Responsive in mittleren bis großen Heaps (Anfrage-Antwort/DB-Interaktionen)

Tipp

Für die meisten allgemeinen Microservice-Anwendungen beginnen Sie mit der Parallel GC.

Ermitteln, wie viele CPU-Kerne benötigt werden

Für jede andere GC als SerialGC empfehlen wir zwei oder mehr vCPU-Kerne - oder mindestens 2000m für cpu_limit auf Kubernetes. Es wird nicht empfohlen, etwas anderes als einen vCPU-Kern in containerisierten Umgebungen auszuwählen.

Tipp

Wenn Sie nicht wissen, mit wie vielen Kernen sie beginnen sollen, ist eine gute Wahl zwei vCPU-Kerne.

Auswählen eines Ausgangspunkts

Es wird empfohlen, mit zwei Replikaten oder Instanzen in Container-Orchestrierungsumgebungen wie Kubernetes, OpenShift, Azure Spring Apps, Azure Container Apps und Azure App Service zu beginnen. In der folgenden Tabelle sind die empfohlenen Ausgangspunkte für die Containerisierung Ihrer neuen Java-Anwendung zusammengefasst.

vCPU-Kerne Containerspeicher JVM-Heapgröße GC Replikate
2 4 GB 75 % ParallelGC 2

Verwenden Sie die folgenden JVM-Parameter:

-XX:+UseParallelGC -XX:MaxRAMPercentage=75

Containerisieren einer vorhandenen lokalen Anwendung

Wenn Ihre Anwendung bereits lokal oder auf einer VM in der Cloud ausgeführt wird, sollten Sie mit der folgenden Konfiguration beginnen:

  • Die gleiche Arbeitsspeichermenge, auf die die Anwendung derzeit Zugriff hat.
  • Die gleiche Anzahl von CPUs oder vCPU-Kernen, die die Anwendung derzeit verfügbar hat.
  • Dieselben JVM-Parameter, die Sie derzeit verwenden.

Wenn die vCPU-Kerne oder die Containerspeicherkombination nicht verfügbar ist, wählen Sie den nächstgelegenen Kern aus, um die vCPU-Kerne und den Containerspeicher aufzurunden.

Nächste Schritte

Nachdem Sie nun die allgemeinen Empfehlungen für die Containerisierung von Java-Anwendungen verstanden haben, fahren Sie mit dem folgenden Artikel fort, um einen Containerisierungsbasisplan einzurichten: