Containerisera dina Java-program

Den här artikeln innehåller en översikt över rekommenderade strategier och inställningar för att containerisera Java-program.

När du containeriserar ett Java-program bör du noga överväga hur mycket CPU-tid containern kommer att ha tillgänglig. Fundera sedan på hur mycket minne som kommer att vara tillgängligt både när det gäller den totala mängden minne och heapstorleken för den virtuella Java-datorn (JVM). I containerbaserade miljöer kan program ha åtkomst till alla processorer och därför kunna köra flera trådar parallellt. Det är dock vanligt att containrar har en cpu-kvot som kan begränsa åtkomsten till processorer.

JVM har heuristik för att fastställa antalet "tillgängliga processorer" baserat på CPU-kvoten, vilket dramatiskt kan påverka prestandan för Java-program. Det minne som allokeras till själva containern och storleken på heapområdet för JVM är lika viktigt som processorerna. Dessa faktorer avgör beteendet för skräpinsamlaren (GC) och systemets övergripande prestanda.

Containerisera ett nytt program

När du containeriserar en Java-arbetsbelastning för ett nytt program måste du ta hänsyn till två saker när du tänker på minne:

  • Det minne som allokerats till själva containern.
  • Mängden minne som är tillgängligt för Java-processen.

Förstå JVM-standardergonom

Program behöver en startpunkt och inställningar. JVM har standardergonom med fördefinierade värden som baseras på antalet tillgängliga processorer och mängden minne i systemet. Standardvärdena som visas i följande tabeller används när JVM startas utan specifika startflaggor eller parametrar.

I följande tabell visas standard-GC som används för de tillgängliga resurserna:

Tillgängliga resurser Standard-GC
Valfritt antal processorer
Upp till 1 791 MB minne
SerialGC
Över 2 processorer
1792 MB eller mer minne
G1GC

I följande tabell visas den maximala standardstorleken för heap beroende på hur mycket minne som är tillgängligt i miljön där JVM körs:

Tillgängligt minne Standardstorlek för maximal heap
Upp till 256 MB 50 % av tillgängligt minne
256 MB till 512 MB ~127 MB
Mer än 512 MB 25 % av det tillgängliga minnet

Standardstorleken för den initiala heapen är 1/64 tillgängligt minne.

Dessa värden är giltiga för OpenJDK 11 och senare och för de flesta distributioner, inklusive Microsoft Build of OpenJDK, Azul Zulu, Eclipse Temurin, Oracle OpenJDK och andra.

Fastställa containerminne

Välj en containerminnesmängd som passar bäst för din arbetsbelastning, beroende på programmets behov och dess distinkta användningsmönster. Om ditt program till exempel skapar stora objektdiagram behöver du förmodligen mer minne än du behöver för program med många små objektdiagram.

Dricks

Om du inte vet hur mycket minne som ska allokeras är en bra startpunkt 4 GB.

Fastställa JVM-heapminne

När du allokerar JVM-heapminne bör du tänka på att JVM behöver mer minne än vad som används för JVM-heapen. När du anger det maximala JVM-heapminnet bör det aldrig vara lika med mängden containerminne eftersom det orsakar fel och containerkrascher i containern.

Dricks

Allokera 75 % av containerminnet för JVM-heapen.

I OpenJDK 11 och senare kan du ange JVM-heapstorleken på följande sätt:

beskrivning Flagga Exempel
Fast värde -Xmx -Xmx4g
Dynamiskt värde -XX:MaxRAMPercentage -XX:MaxRAMPercentage=75

Minsta/inledande heapstorlek

Om miljön garanterat har en viss mängd minne reserverat till en JVM-instans, till exempel i en container, bör du ange den minsta heapstorleken – eller den ursprungliga heapstorleken – till samma storlek som den maximala heapstorleken. Den här inställningen anger för JVM att den inte ska utföra uppgiften att frigöra minne till operativsystemet.

Om du vill ange en minsta heapstorlek använder du -Xms för absoluta belopp eller -XX:InitialRAMPercentage för procentbelopp.

Viktigt!

Flaggan -XX:MinRAMPercentage, trots vad namnet antyder, används för att ange den maximala STANDARD-RAM-procentandelen för system med upp till 256 MB RAM-minne tillgängligt i systemet.

Chart showing the default heap size on OpenJDK 17.

Avgöra vilken GC som ska användas

Tidigare fastställde du hur mycket JVM-heapminne som ska börja med. Nästa steg är att välja din GC. Mängden maximalt JVM-heapminne som du har är ofta en faktor för att välja din GC. I följande tabell beskrivs egenskaperna för varje GC.

Faktorer SerialGC ParallelGC G1GC ZGC ShenandoahGC
Antal kärnor 1 2 2 2 2
Flera trådar Nej Ja Ja Ja Ja
Java-heapstorlek <4 GByte <4 GByte >4 GByte >4 GByte >4 GByte
Pausa Ja Ja Ja Ja (<1 ms) Ja (<10 ms)
Omkostnader Minimal Minimal Medel Medel Medel
Slutsvarstidseffekt Högst Högst Högst Lägst Medel
JDK-version Alla Alla JDK 8+ JDK 17+ JDK 11+
Bäst för Små heaps med en kärna Små heaps- eller batcharbetsbelastningar med flera kärnor med valfri heapstorlek Dynamisk i medelstora till stora heaps (begäran-svar/DB-interaktioner) Dynamisk i medelstora till stora heaps (begäran-svar/DB-interaktioner) Dynamisk i medelstora till stora heaps (begäran-svar/DB-interaktioner)

Dricks

För de flesta allmänna mikrotjänstprogram börjar du med Parallell GC.

Fastställa hur många CPU-kärnor som behövs

För andra GC-enheter än SerialGC rekommenderar vi två eller flera vCPU-kärnor – eller minst 2000mcpu_limit på Kubernetes. Vi rekommenderar inte att du väljer något mindre än 1 vCPU-kärna i containerbaserade miljöer.

Dricks

Om du inte vet hur många kärnor du ska börja med är ett bra val 2 vCPU-kärnor.

Välj en startpunkt

Vi rekommenderar att du börjar med två repliker eller instanser i containerorkestreringsmiljöer som Kubernetes, OpenShift, Azure Spring Apps, Azure Container Apps och Azure App Service. I följande tabell sammanfattas de rekommenderade startpunkterna för containeriseringen av ditt nya Java-program.

vCPU-kärnor Containerminne JVM-heapstorlek GC Repliker
2 4 GB 75 % ParallelGC 2

De JVM-parametrar som ska användas är: -XX:+UseParallelGC -XX:MaxRAMPercentage=75

Containerisera ett befintligt (lokalt) program

Om programmet redan körs lokalt eller på en virtuell dator i molnet rekommenderar vi att du börjar med:

  • Samma mängd minne som programmet för närvarande har åtkomst till.
  • Samma antal processorer (vCPU-kärnor) som programmet för närvarande har tillgängligt.
  • Samma JVM-parametrar som du använder för närvarande.

Om kombinationen av vCPU-kärnor och/eller containerminne inte är tillgänglig väljer du den närmaste och avrundar vCPU-kärnorna och containerminnet.

Nästa steg

Nu när du förstår de allmänna rekommendationerna för att containerisera Java-program fortsätter du till följande artikel för att upprätta en containeriseringsbaslinje: