Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este artículo se proporciona información general sobre las estrategias y la configuración recomendadas para la contenedorización de aplicaciones Java. Al incluir en contenedores una aplicación de Java, tenga en cuenta cuidadosamente cuánto tiempo de CPU tiene disponible el contenedor. A continuación, tenga en cuenta la cantidad de memoria disponible en términos de la cantidad total de memoria y el tamaño del montón de la máquina virtual (JVM) de Java. En entornos en contenedores, es posible que las aplicaciones tengan acceso a todos los procesadores y, por tanto, puedan ejecutar varios subprocesos en paralelo. Sin embargo, es habitual que los contenedores tengan aplicada una cuota de CPU que podría limitar el acceso a las CPU.
JVM usa heurística para determinar el número de "procesadores disponibles" en función de la cuota de CPU, lo que puede influir considerablemente en el rendimiento de las aplicaciones de Java. La memoria asignada al propio contenedor y el tamaño del área de montón de la JVM son tan importantes como los procesadores. Estos factores determinan el comportamiento del recolector de elementos no utilizados (GC) y el rendimiento general del sistema.
Contenedorización de una nueva aplicación
Al contenizar una carga de trabajo de Java para una nueva aplicación, tenga en cuenta dos aspectos sobre la memoria:
- Memoria asignada al propio contenedor.
- Cantidad de memoria disponible para el proceso de Java.
Descripción de la ergonómica predeterminada de JVM
Las aplicaciones necesitan un punto de partida y una configuración. JVM tiene la ergonómica predeterminada con valores predefinidos que se basan en el número de procesadores disponibles y la cantidad de memoria en el sistema. JVM usa los valores predeterminados que se muestran en las tablas siguientes cuando se inicia sin marcas de inicio o parámetros específicos.
En la tabla siguiente se muestra el GC predeterminado para los recursos disponibles:
| Recursos disponibles | GC predeterminado |
|---|---|
| Cualquier número de procesadores Hasta 1791 MB de memoria |
SerialGC |
| Más de 2 procesadores 1792 MB o más de memoria |
G1GC |
En la tabla siguiente se muestra el tamaño máximo predeterminado del montón en función de la cantidad de memoria disponible en el entorno en el que se ejecuta la JVM:
| Memoria disponible | Tamaño máximo predeterminado del montón |
|---|---|
| Hasta 256 MB | 50 % de memoria disponible |
| 256 MB a 512 MB | ~127 MB |
| Más de 512 MB | 25 % de memoria disponible |
El tamaño del montón inicial predeterminado es 1/64 de memoria disponible. Estos valores son válidos para OpenJDK 11 y versiones posteriores, y para la mayoría de las distribuciones, como Microsoft Build de OpenJDK, Azul Zulu, Eclipse Temurin, Oracle OpenJDK y otros.
Determinación de la memoria del contenedor
Elija una cantidad de memoria de contenedor que sirva mejor a la carga de trabajo, según las necesidades de la aplicación y sus patrones de uso distintivos. Por ejemplo, si la aplicación crea gráficos de objetos grandes, probablemente necesite más memoria de la que necesitaría para las aplicaciones con muchos gráficos de objetos pequeños.
Sugerencia
Si no sabe cuánta memoria asignar, un buen punto de partida es de 4 GB.
Determinar la memoria del heap de JVM
Cuando asignas memoria heap a la JVM, recuerda que la JVM necesita más memoria que la cantidad que asignas a la memoria heap. No establezca la memoria máxima del montón de JVM para que sea igual a la cantidad de memoria del contenedor. Esta configuración puede provocar errores de memoria insuficiente (OOM) y bloqueos del contenedor.
Sugerencia
Asigne el 75 % de memoria del contenedor a la pila de JVM.
En OpenJDK 11 y versiones posteriores, establezca el tamaño del montón de JVM de una de las maneras siguientes:
| Descripción | Bandera | Ejemplos |
|---|---|---|
| Valor fijo | -Xmx |
-Xmx4g |
| Valor dinámico | -XX:MaxRAMPercentage |
-XX:MaxRAMPercentage=75 |
Tamaño mínimo o inicial del montón
Si el entorno garantiza una determinada cantidad de memoria reservada a una instancia de JVM, como en un contenedor, establezca el tamaño mínimo del montón o el tamaño del montón inicial en el mismo tamaño que el tamaño máximo del montón. Esta configuración indica a la JVM que no debe realizar la tarea de liberar memoria al sistema operativo.
Para establecer un tamaño mínimo de montón, use -Xms para cantidades absolutas o -XX:InitialRAMPercentage para cantidades porcentuales.
Importante
A pesar de lo que sugiere el nombre, la marca -XX:MinRAMPercentage establece el porcentaje de RAM máximo predeterminado para los sistemas con hasta 256 MB de RAM disponibles en el sistema.
Determinar qué GC usar
Anteriormente, determinó la cantidad de memoria del montón de JVM con la que empezar. El siguiente paso es elegir a su contratista general. La cantidad máxima de memoria heap de la JVM de la que dispone suele influir en la elección del GC. En la tabla siguiente se describen las características de cada GC.
| Factores | SerialGC | ParallelGC | G1GC | ZGC | ShenandoahGC |
|---|---|---|---|---|---|
| Número de núcleos | 1 | 2 | 2 | 2 | 2 |
| Multithreaded | No | Sí | Sí | Sí | Sí |
| Tamaño del montón de Java | <4 GB | <4 GB | >4 GB | >4 GB | >4 GB |
| Pausa | Sí | Sí | Sí | Sí (<1 ms) | Sí (<10 ms) |
| Gastos generales | Mínimo | Mínimo | Moderada | Moderada | Moderada |
| Efecto de latencia de cola | Alto | Alto | Alto | Bajo nivel | Moderada |
| Versión de JDK | Todos | Todos | JDK 8+ | JDK 17+ | JDK 11+ |
| Más adecuado para | Montones pequeños de núcleo único | Montones pequeños de varios núcleos o cargas de trabajo por lotes con cualquier tamaño de montón | Capacidad de respuesta en montones de tamaño mediano a grande (interacciones de solicitud-respuesta o de base de datos) | Capacidad de respuesta en montones de tamaño mediano a grande (interacciones de solicitud-respuesta o de base de datos) | Capacidad de respuesta en montones de tamaño mediano a grande (interacciones de solicitud-respuesta o de base de datos) |
Sugerencia
Para la mayoría de las aplicaciones de microservicios de uso general, comience con la GC paralela.
Determinar cuántos núcleos de CPU necesita
Para cualquier GC que no sea SerialGC, use dos o más núcleos de vCPU, o al menos 2000m para cpu_limit en Kubernetes. No seleccione menos de un núcleo de vCPU en entornos en contenedores.
Sugerencia
Si no sabe cuántos núcleos empezar, una buena opción es dos núcleos de vCPU.
Selección de un punto de partida
Comience con dos réplicas o instancias en entornos de orquestación de contenedores como Kubernetes, OpenShift, Azure Spring Apps, Azure Container Apps y Azure App Service. En la tabla siguiente se resumen los puntos de partida recomendados para la contenedorización de la nueva aplicación Java.
| Núcleos de vCPU | Memoria de contenedor | Tamaño del montón de JVM | GC | Réplicas |
|---|---|---|---|---|
| 2 | 4 GB | 75 % | ParallelGC | 2 |
Use los siguientes parámetros de JVM:
-XX:+UseParallelGC -XX:MaxRAMPercentage=75
Contenedorización de una aplicación local existente
Si la aplicación ya se está ejecutando localmente o en una máquina virtual en la nube, comience con la siguiente configuración:
- La misma cantidad de memoria a la que tiene acceso la aplicación actualmente.
- El mismo número de CPU o núcleos de vCPU que la aplicación tiene disponible actualmente.
- Los mismos parámetros de JVM que usa actualmente.
Si los núcleos de vCPU o la combinación de memoria del contenedor no están disponibles, elija el más cercano, redondeando los núcleos de vCPU y la memoria del contenedor.
Pasos siguientes
Ahora que comprende las recomendaciones generales para la inclusión en contenedores de aplicaciones Java, continúe con el siguiente artículo para establecer una línea base de contenedorización: