Java Virtual Machine - JVM em containers garante escalabilidade vertical de memória
Atualmente, aplicativos baseados em JVM podem se beneficiar da elasticidade e densidade da tecnologia de contêineres.
No entanto, ainda existem alguns problemas que impedem o aproveitamento de todo o potencial do Java e dos contêineres “casamento”.
Liberar memória Heap não utilizada, porém comprometida, pelas principais implementações de JVM baseadas no OpenJDK, na maioria dos casos, não é executada automaticamente ou requer conhecimento específico a ser configurado.
Para resolver esse problema e tornar o uso da RAM Java em contêineres mais eficiente, a equipe da SaveinCloud colaborou com diferentes especialistas envolvidos no desenvolvimento da JVM.
Periodicamente é publicado artigos destacando esta questão e motivando a comunidade a ajudar na busca de uma solução. Como resultado, a atenção para este tópico aumentou e novas melhorias foram introduzidas em diferentes implementações da Garbage Collection.
Além disso, iniciamos e patrocinamos o desenvolvimento de um patch para o OpenJDK, que melhora a elasticidade e permite o dimensionamento vertical totalmente automatizado de aplicativos Java que dependem do coletor de lixo G1. Este trabalho introduz novas opções de linha de comando para dimensionamento de heap que permite que a JVM dimensione seus recursos de memória verticalmente.
Em particular, a solução proposta é devolver imediatamente a memória confirmada não utilizada ao sistema operacional.
Há uma necessidade de repensar as políticas de coleta de lixo (GC) que controlam quanto e quando a memória de heap é devolvida ao sistema operacional.
Atualmente, o G1 retorna a memória do heap Java apenas em um GC Completo que raramente é executado.
Como resultado, na maioria dos casos, o heap Java não será liberado, a menos que seja forçado externamente.
Esse comportamento é particularmente desvantajoso em ambientes de contêineres escaláveis quando a JVM usa uma fração dos recursos de memória designados devido à inatividade ou a uma pequena carga. Isso resulta em clientes pagando em excesso por recursos não utilizados e os provedores de nuvem não sendo capazes de utilizar totalmente seu hardware.
Para superar esse problema, introduzimos lógica adicional na JVM para acionar uma redução de heap sempre que a quantidade de memória não utilizada for significativa. Ele pode ser executado a qualquer momento por opções configuráveis, não apenas durante ciclos regulares de GC.
Durante a inatividade da aplicação, o G1 acionará periodicamente um ciclo concorrente devido às seguintes condições:
- Mais de milissegundos G1PeriodicGCInterval passaram desde qualquer pausa na coleta de lixo anterior e não há nenhum ciclo concorrente em andamento neste momento. Um valor zero indica que as coletas de lixo periódicas para recuperar prontamente a memória estão desabilitadas.
- O valor médio de carregamento de um minuto do sistema, conforme retornado pela chamada getloadavg() no sistema host da JVM (por exemplo, contêiner), está abaixo de G1PeriodicGCSystemLoadThreshold. Essa condição é ignorada se G1PeriodicGCSystemLoadThreshold for zero.
Se qualquer uma dessas condições não for atendida, a coleta de lixo periódica atual será cancelada e será reconsiderada quando o tempo G1PeriodicGCInterval passar.
A solução oferecida já está implementada no OpenJDK 12. Essa melhoria permitirá que os usuários de Java economizem uma quantidade significativa de recursos e dinheiro, além de ajudar os provedores de nuvem a utilizar melhor sua infraestrutura e introduzir um modelo de faturamento mais flexível com base no uso real não nos limites da VM.
O problema declarado de elasticidade de Java, detalhes sobre experimentos executados e especificações do patch OpenJDK correspondente foram apresentados no Oracle Code One 2018 durante a sessão de Ruslan Synytsky, CEO da Virtuozzo. Veja abaixo a apresentação sobre o assunto.
Quer viver esta experiência na prática? Conheça a plataforma da SaveinCloud e teste gratuitamente por 14 dias!
Fonte: Virtuozzo