Java: limite la cantidad de núcleos que una JVM puede usar

Java: limite la cantidad de núcleos que una JVM puede usar

Varios usuarios ejecutan aplicaciones Java en un servidor informático de 60 núcleos (basado en Linux/Ubuntu). Existen diferentes aplicaciones y la mayoría de ellas no se desarrollan internamente.

Si bien el administrador del sistema cree que está bien que el proceso Java de un usuario determinado use 10 núcleos en un momento dado, le gustaría que no usaran más de 10.

¿Existe alguna configuración de Java o del sistema operativo que pueda usarse para evitar que el proceso simplemente se apodere de recursos informáticos de forma ilimitada?

Respuesta1

En el frente del sistema operativo:

  • Yo diría que el método clásico es establecer la afinidad de la CPU con taskset.

  • Una mejor alternativa es utilizarcgroups.

  • Y la solución de moda es ejecutar sus aplicaciones enEstibadorcontenedores. Sin embargo, antes de Java 8, la JVM no es capaz de comprender las limitaciones impuestas por Docker (solo disponible después del backport 8u131+, no estoy seguro si está disponible como experimental en Java9 para la parte de la CPU, pero es para la memoria y está completamente disponible en java10)

Respuesta2

Yo diría que vale la pena ver este vídeo.https://vimeo.com/181900266

Ofrece una muy buena descripción general sobre Java, cgroups y contenedores, y cómo la JVM descubre, por ejemplo, el número de CPU.

En base a esto, diría que hasta Java 8 la JVM determina la cantidad de CPU disponibles de manera que siempre considera que todas las CPU "en línea" están disponibles para ella, porque usa sysconf(_SC_NPROCESSORS_ONLN) para este propósito. Incluso si está agrupado o puesto en un contenedor.

Desde Java 9, JVM usará sched_getaffinity() y será útil si se usa cpuset para controlar la cantidad de CPU para la JVM. Es decir, la JVM verá sólo las CPU configuradas. Por ejemplo, si uno usa la opción cpuset-cpus de Docker, realmente creará un límite para la JVM. ¡Nota! Si cpushare está configurado para la JVM, eso aún no proporciona una solución al problema. La JVM seguirá viendo todas las CPU del sistema (sin importar si está en un contenedor) si solo se configura cpushare.

Respuesta3

Otra alternativa además de lo que otros han mencionado (cuota de cgroup, cpuset de cgroup) es que puede decirle explícitamente a Java cuántas CPU debe informar cuando las bibliotecas lo soliciten proporcionando un valor para la -XX:ActiveProcessorCountopción. Cualquier biblioteca que elija automáticamente el número de subprocesos en función del valor de Runtime.getRuntime().availableProcessors()(como Reactor's Schedulers.parallel()) se configurará en consecuencia. También podría informar la configuración automática del recolector de basura.

información relacionada