Lanzo nuestra aplicación Spring Boot en el contenedor docker en el servicio AWS Fargate, por lo que una vez que el consumo de CPU alcanza más del 100%, el contenedor se detiene Docker OOM-killer con error
Razón: OutOfMemoryError: contenedor eliminado debido al uso de memoria
En las métricas, podemos ver que la CPU se vuelve más del 100%. Parece que después de un tiempo de perfilar encontramos un código que consume CPU, pero mi pregunta es, ¿cómo la CPU puede ser superior al 100%?
¿Es alguna forma de decir que JVM usa solo el 100%?
Recuerdo que tuvimos un problema similar con el consumo de memoria. Leí muchos artículos sobre cgroups, y se encontró la solución para especificar
-XX:+DesbloquearExperimentalVMOptions -XX:+UsarCGroupMemoryLimitForHeap
Entonces, cuando inicie la ventana acoplable con la opción -m = 512, el tamaño del montón será 1/4 del tamaño de mac. El tamaño del montón también se puede ajustar con la opción
-XX: MaxRAMFraction=2
que asignará la mitad de la memoria acoplable para el montón. ¿Debo usar algo similar para la CPU? Leí el artículo https://blogs.oracle.com/java-platform-group/java-se-support-for-docker-cpu-and-memory-limits , pero dice que
A partir de Java SE 8u131 y en JDK 9, la JVM es consciente de Docker con respecto a los límites de CPU de Docker de forma transparente. Eso significa que si -XX:ParalllelGCThreads o -XX:CICompilerCount no se especifican como opciones de línea de comando, la JVM aplicará el límite de CPU de Docker como la cantidad de CPU que la JVM ve en el sistema. Luego, la JVM ajustará la cantidad de subprocesos GC y los subprocesos del compilador JIT como si se estuviera ejecutando en un sistema completo con la cantidad de CPU establecida como el límite de CPU de Docker.
El comando Docker se usa para comenzar
docker run -d .... -e JAVA_OPTS='-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:+PrintFlagsFinal -XshowSettings:vm' -m=512 -c=256 ...Se utiliza la versión de Java
openjdk version "1.8.0_181" OpenJDK Runtime Environment (build 1.8.0_181-8u181-b13-1~deb9u1-b13) OpenJDK 64-Bit Server VM (build 25.181-b13, mixed mode)Alguna información adicional sobre la aplicación durante el inicio
VM settings: Max. Heap Size (Estimated): 123.75M Ergonomics Machine Class: client Using VM: OpenJDK 64-Bit Server VM ParallelGCThreads = 0 CICompilerCount := 2 CICompilerCountPerCPU = trueEncontré respuesta a mi pregunta. El comportamiento para identificar la cantidad de procesadores a usar se corrigió en https://bugs.openjdk.java.net/browse/JDK-8146115
Número de CPU
Utilice una combinación de number_of_cpus() y cpu_sets() para determinar cuántos procesadores están disponibles para el proceso y ajuste las JVM os::active_processor_count adecuadamente. El número_de_cpus() se calculará en función de cpu_quota() y cpu_period() mediante esta fórmula: número_de_cpus() = cpu_cuota() / cpu_period(). Si se ha configurado cpu_shares para el contenedor, number_of_cpus() se calculará en función de cpu_shares()/1024. 1024 es la unidad predeterminada y estándar para calcular el uso relativo de la CPU en el software de administración de contenedores basado en la nube.
Agregue también un nuevo indicador de VM (-XX:ActiveProcessorCount=xx) que permita anular la cantidad de CPU. Este indicador se respetará incluso si UseContainerSupport no está habilitado.
Entonces, en AWS, generalmente configura cpu_shares en el nivel de definición de tareas. Antes de jvm fix, se calculó incorrectamente.
En la versión java8 < 191: cpu_shares()/1024 = 256/1024 = se identificó como 2
Después de la migración en la versión java8 > 191: cpu_shares()/1024 = 256/1024 = se identificó como 1
El código a probar
val version = System.getProperty("java.version") val runtime = Runtime.getRuntime() val processors = runtime.availableProcessors() logger.info("========================== JVM Info ==========================") logger.info("Java version is: {}", version) logger.info("Available processors: {}", processors)La salida de muestra
"Java version is: 1.8.0_212" "Available processors: 1"Espero que ayude a alguien, ya que no puedo encontrar la respuesta en ninguna parte (rastreador de problemas de primavera, soporte de AWS, etc.)