
Vários usuários estão executando aplicativos Java em um servidor de computação de 60 núcleos (baseado em Linux/Ubuntu). Existem diferentes aplicações e a maioria delas não é desenvolvida internamente.
Embora o administrador do sistema ache que não há problema para o processo Java de um determinado usuário usar 10 núcleos a qualquer momento, ela gostaria que eles não usassem mais de 10.
Existe alguma configuração de Java ou sistema operacional que possa ser usada para evitar que o processo capture recursos de computação de forma ilimitada?
Responder1
Na frente do sistema operacional:
Eu diria que o método clássico é definir a afinidade da CPU com o
taskset
.Uma alternativa melhor é usar
cgroups
.E a solução mais popular é executar seus aplicativos emDockercontainers. No entanto, antes do Java 8, a JVM não é capaz de entender as limitações impostas pelo Docker (disponível apenas após backport 8u131+, não tenho certeza se está disponível como experimental em Java9 para a parte da CPU, mas é para memória, e totalmente disponível em Java10)
Responder2
Eu diria que vale a pena ver este vídeo.https://vimeo.com/181900266
Ele fornece uma visão geral muito boa sobre Java versus cgroups versus contêineres e como a JVM descobre, por exemplo, o número de CPUs.
Com base nisso eu diria que até o Java 8 a JVM determina a quantidade de CPUs disponíveis de uma forma, que ela sempre considera que todas as CPUs "online" estão disponíveis para ela, pois utiliza sysconf(_SC_NPROCESSORS_ONLN) para esse fim. Mesmo que seja cgroup ou colocado em um contêiner.
A partir do Java 9, a JVM usará sched_getaffinity() e ajudará se cpuset for usado para controlar o número de CPUs da JVM. Ou seja, a JVM verá apenas as CPUs configuradas. Por exemplo, se alguém usar a opção cpuset-cpus do Docker, isso realmente criará um limite para a JVM. Observação! Se o cpushare estiver configurado para a JVM, isso ainda não fornece uma solução para o problema. A JVM ainda verá todas as CPUs do sistema (não importa se está em um contêiner) se apenas o cpushare estiver configurado.
Responder3
Outra alternativa além do que outros mencionaram (cgroup quota, cgroup cpuset) é que você pode dizer explicitamente ao Java quantas CPUs ele deve relatar quando as bibliotecas solicitarem, fornecendo um valor para a -XX:ActiveProcessorCount
opção. Quaisquer bibliotecas que escolham automaticamente a contagem de threads com base no valor de Runtime.getRuntime().availableProcessors()
(como a do Reactor Schedulers.parallel()
) serão configuradas de acordo. Também pode informar a configuração automática do Coletor de Lixo.