Несколько пользователей запускают Java-приложения на 60-ядерном вычислительном сервере (на базе Linux / Ubuntu). Существуют разные приложения, и большинство из них не разрабатываются собственными силами.
Хотя системный администратор считает, что для Java-процесса данного пользователя нормально использовать 10 ядер в любой момент времени, он хотел бы, чтобы они не использовали более 10 ядер.
Есть ли какая-либо конфигурация Java или ОС, которая может использоваться для предотвращения неограниченного захвата вычислительного ресурса процессом?
На передней панели ОС:
Я бы сказал, что классический метод - установить соответствие процессора с taskset
.
Лучшая альтернатива - использовать cgroups
.
Модное решение - запускать приложения в Докер контейнеры. Однако до Java 8 JVM не могла понять ограничения, налагаемые Docker (доступно только после бэкпорта 8u131 +, не уверен, что он доступен как экспериментальный в Java9 для части ЦП, но он предназначен для памяти и полностью доступен в Java10)
Я бы сказал, стоит посмотреть это видео. https://vimeo.com/181900266
Он дает очень хороший обзор Java, контрольных групп и контейнеров, а также того, как JVM узнает, например количество процессоров.
Основываясь на этом, я бы сказал, что до Java 8 JVM определяет количество доступных процессоров на пути, что она всегда считает, что для нее доступны все «онлайн» процессоры, потому что для этой цели она использует sysconf (_SC_NPROCESSORS_ONLN). Даже если это cgroup'd или помещено в контейнер.
Начиная с Java 9 JVM будет использовать sched_getaffinity (), и это поможет, если cpuset используется для управления количеством процессоров для JVM. Т.е. JVM будет видеть только сконфигурированные процессоры. Например, если кто-то использует параметр Docker cpuset-cpus, он действительно создаст ограничение для JVM. Заметка! Если cpushare настроен для JVM, это все еще не дает решения проблемы. JVM по-прежнему будет видеть все процессоры в системе (независимо от того, находится ли он в контейнере), если настроен только cpushare.