Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questo articolo offre una panoramica delle strategie e delle impostazioni consigliate per l'inserimento in contenitori di applicazioni Java. Quando si containerizza un'applicazione Java, valutare attentamente quanto tempo di CPU è disponibile per il contenitore. Valutare quindi la quantità di memoria disponibile sia in termini di quantità totale di memoria che delle dimensioni dell'heap della macchina virtuale Java (JVM). Negli ambienti in contenitori, le applicazioni potrebbero avere accesso a tutti i processori e quindi essere in grado di eseguire più thread in parallelo. È tuttavia comune che i contenitori abbiano una quota di CPU applicata che potrebbe limitare l'accesso alle CPU.
La JVM ha euristica per determinare il numero di "processori disponibili" in base alla quota della CPU, che può influenzare notevolmente le prestazioni delle applicazioni Java. La memoria allocata al contenitore stesso e le dimensioni dell'area dell'heap per la JVM sono importanti come i processori. Questi fattori determinano il comportamento del Garbage Collector (GC) e le prestazioni complessive del sistema.
Containerizzare una nuova applicazione
Quando si inserisce in contenitori un carico di lavoro Java per una nuova applicazione, è necessario tenere conto di due aspetti quando si pensa alla memoria:
- Memoria allocata al contenitore stesso.
- Quantità di memoria disponibile per il processo Java.
Informazioni sull'ergonomicità predefinita di JVM
Le applicazioni necessitano di un punto di partenza e di impostazioni. La JVM dispone di ergonomiche predefinite con valori predefiniti basati sul numero di processori disponibili e sulla quantità di memoria nel sistema. I valori predefiniti mostrati nelle tabelle seguenti vengono usati quando la JVM viene avviata senza flag di avvio o parametri specifici.
La tabella seguente illustra l'GC predefinito usato per le risorse disponibili:
| Risorse disponibili | GC predefinito |
|---|---|
| Numero qualsiasi di processori Fino a 1.791 MB di memoria |
SerialGC |
| almeno 2 processori 1.792 MB o più di memoria |
G1GC |
La tabella seguente mostra la dimensione massima predefinita dell'heap a seconda della quantità di memoria disponibile nell'ambiente in cui è in esecuzione la JVM:
| Memoria disponibile | Dimensioni massime predefinite dell'heap |
|---|---|
| Fino a 256 MB | 50% di memoria disponibile |
| Da 256 MB a 512 MB | ~127 MB |
| Più di 512 MB | 25% di memoria disponibile |
La dimensione dell'heap iniziale predefinita è 1/64 della memoria disponibile. Questi valori sono validi per OpenJDK 11 e versioni successive e per la maggior parte delle distribuzioni, tra cui Microsoft Build of OpenJDK, Azul Zulu, EclipseTemo, Oracle OpenJDK e altri.
Determinare la memoria del contenitore
Selezionare una quantità di memoria del contenitore che soddisfi al meglio il carico di lavoro, a seconda delle esigenze dell'applicazione e dei relativi modelli di utilizzo distintivi. Ad esempio, se l'applicazione crea grafici a oggetti di grandi dimensioni, è probabile che sia necessaria una quantità di memoria superiore a quella necessaria per le applicazioni con molti piccoli grafici a oggetti.
Suggerimento
Se non si conosce la quantità di memoria da allocare, un buon punto di partenza è 4 GB.
Determinare la memoria heap della JVM
Quando si alloca memoria heap JVM, la JVM richiede più memoria rispetto a quella utilizzata per l'heap JVM. Quando si imposta la memoria heap massima della JVM, non deve mai essere uguale alla quantità di memoria del contenitore perché ciò causa errori di esaurimento della memoria (OOM) e crash del contenitore.
Suggerimento
Allocare 75% di memoria del contenitore per l'heap JVM.
In OpenJDK 11 e versioni successive è possibile impostare le dimensioni dell'heap JVM nei modi seguenti:
| Descrizione | Bandiera | Esempi |
|---|---|---|
| Valore fisso | -Xmx |
-Xmx4g |
| Valore dinamico | -XX:MaxRAMPercentage |
-XX:MaxRAMPercentage=75 |
Dimensione minima/iniziale dell'heap
Se l'ambiente ha la certezza di avere una certa quantità di memoria riservata a un'istanza di JVM, ad esempio in un contenitore, è necessario impostare le dimensioni minime dell'heap, o le dimensioni iniziali dell'heap, sulle stesse dimensioni dell'heap massimo. Questa impostazione indica alla JVM che non deve eseguire l'attività di liberare memoria al sistema operativo.
Per impostare una dimensione minima dell'heap, utilizzare -Xms per gli importi assoluti o -XX:InitialRAMPercentage per gli importi percentuali.
Importante
Il flag -XX:MinRAMPercentage, nonostante ciò che suggerisce il nome, viene usato per impostare la percentuale di RAM massima predefinita per i sistemi con un massimo di 256 MB di RAM disponibile nel sistema.
Determinare quale GC usare
In precedenza, è stata determinata la quantità di memoria heap JVM da cui iniziare. Il passaggio successivo consiste nel scegliere il GC. La quantità massima di memoria heap JVM che si ha spesso è un fattore nella scelta del catalogo globale. Nella tabella seguente vengono descritte le caratteristiche di ogni GC.
| Fattori | SerialGC | ParallelGC | G1GC | ZGC | ShenandoahGC |
|---|---|---|---|---|---|
| Numero di core | 1 | 2 | 2 | 2 | 2 |
| Multithreading | NO | Sì | Sì | Sì | Sì |
| Dimensioni dell'heap Java | <4 GBytes | <4 GBytes | >4 GBytes | >4 GBytes | >4 GBytes |
| Pausa | Sì | Sì | Sì | Sì (<1 ms) | Sì (<10 ms) |
| Costi generali | Minimo | Minimo | Moderato | Moderato | Moderato |
| Effetto della latenza finale | Alto | Alto | Alto | Basso livello | Moderato |
| Versione di JDK | Tutti | Tutti | JDK 8+ | JDK 17+ | JDK 11+ |
| Il migliore per | Heap piccoli a core singolo | Heap di piccole dimensioni multi-core o carichi di lavoro batch con qualsiasi dimensione dell'heap | Reattivo in heap di dimensioni medio-grandi (interazioni request-response/DB) | Reattivo in heap di dimensioni medio-grandi (interazioni request-response/DB) | Reattivo in heap di dimensioni medio-grandi (interazioni request-response/DB) |
Suggerimento
Per la maggior parte delle applicazioni di microservizi per utilizzo generico, iniziare con Parallel GC.
Determinare il numero di core CPU necessari
Per qualsiasi GC diverso da SerialGC, è consigliabile usare due o più core vCPU o almeno 2000m per cpu_limit in Kubernetes. Non è consigliabile selezionare nulla di meno di un core vCPU in ambienti in contenitori.
Suggerimento
Se non si conosce il numero di core da cui iniziare, una buona scelta è due core vCPU.
Selezionare un punto di partenza
È consigliabile iniziare con due repliche o istanze in ambienti di orchestrazione dei contenitori come Kubernetes, OpenShift, App Spring di Azure, App Contenitore di Azure e Servizio app di Azure. La tabella seguente riepiloga i punti di partenza consigliati per la containerizzazione della nuova applicazione Java.
| Core della vCPU | Memoria del contenitore | Dimensioni dell'heap JVM | GC | Repliche |
|---|---|---|---|---|
| 2 | 4 GB | 75% | ParallelGC | 2 |
Usare i parametri JVM seguenti:
-XX:+UseParallelGC -XX:MaxRAMPercentage=75
Containerizzare un'applicazione locale esistente
Se l'applicazione è già in esecuzione in locale o in una macchina virtuale nel cloud, è consigliabile iniziare con la configurazione seguente:
- La stessa quantità di memoria a cui l'applicazione ha attualmente accesso.
- Lo stesso numero di CPU o core vCPU disponibili attualmente per l'applicazione.
- Gli stessi parametri JVM attualmente usati.
Se la combinazione di core vCPU o memoria del contenitore non è disponibile, selezionare quella più vicina, arrotondando i core vCPU e la memoria del contenitore.
Passaggi successivi
Dopo aver compreso le raccomandazioni generali per la containerizzazione di applicazioni Java, continuare con l'articolo seguente per stabilire una baseline di containerizzazione: