Introdução à multitenancy do Java

Saiba mais sobre os novos recursos para os sistemas de nuvem no IBM Java 8 beta

Recentemente, o IBM Multitenant JVM ficou disponível como parte do IBM Java ™ 8 beta. Executando diversos aplicativos em um único JVM de vários proprietários, um sistema de nuvem pode acelerar o tempo de inicialização desses aplicativos e reduzir a área de cobertura da memória. Este artigo apresenta a tecnologia por trás do JVM de nuvem com vário s proprietários e discute os principais custos e benefícios.

Graeme Johnson, J9 Virtual Machine Development Manager, IBM  

Graeme JohnsonGraeme Johnson é gerente de desenvolvimento e líder técnico na equipe do IBM J9 Virtual Machine. Ele desenvolve máquinas virtuais e depuradores desde que passou a fazer parte da IBM (e, anteriormente, Object Technology International) em 1994. Trabalhou com os tempos de execução do VisualAge for Java e do IBM/OTI Smalltalk. Recentemente, Graeme se concentra no projeto Apache Harmony e no suporte do tempo de execução do Java/PHP para o IBM Project Zero. É palestrante frequente sobre diversos tópicos, que incluem: Apache Harmony no JavaOne 2006, desenvolvimento de multiplataforma C no EclipseCon 2007 e uma exame do tempo de execução do PHP no International PHP 2006.



Michael Dawson, Software Developer, IBM  

Michael DawsonMichael Dawson trabalhou com a equipe do J9 JVM durante os últimos nove anos, implementando os componentes principais do JVM. Ele contribuiu com as entregas do IBM Java ao longo dos anos, incluindo o WebSphere Real Time, além dos releases do Java 6 e Java 7 nas plataformas. Nos últimos anos, contribuiu para a nuvem IBM e com esforços de virtualização para a tecnologia Java. No passado, liderou equipes que desenvolveram aplicativos de e-commerce e os entregaram como serviços, incluindo serviços de comunicação, processamento de cartões de crédito, auditorias online e faturamento eletrônico.



01/Nov/2013

Os provedores de nuvem devem considerar o custo da infraestrutura necessária para executar sistemas e entregar serviços em relação aos benefícios gerados por eles. Essas considerações de custo-benefício levam os provedores e refletirem sobre várias arquiteturas. As escolhas abrangem uma grande faixa de opções que vai de arquiteturas não compartilhadas a compartilhadas com vários proprietários . Sem compartilhamento, o provedor oferece hardware, software e aplicativos completamente dedicados a clientes individuais. No multitenancy compartilhado, diversos aplicativos de clientes são suportados por um único aplicativo. Todo hardware e software subjacente é compartilhado.

A maior implicação da mudança para esse espectro de arquitetura é isolamento versus densidade. Densidade é o número de sistemas e serviços que podem ser entregues para um conjunto específico de hardware e software. Quanto maior o compartilhamento, maior a densidade. Densidades maiores reduzem os custos dos provedores. Ao mesmo tempo, maior compartilhamento reduz o nível de isolamento entre os proprietários— dos sistemas individuais ou serviços entregues. O isolamento é o grau em que um proprietário pode afetar a atividade ou os dados de outros proprietários.

Para proprietários baseados em Java, as posições ao longo do espectro de arquitetura incluem compartilhamento ou não compartilhamento de JVM. Em qualquer arquitetura em que os aplicativos de nível superior são compartilhados, o JVM também deve ser compartilhado. O compartilhamento do JVM economiza memória e tempo do processador. Mas com a tecnologia JVM tradicional, o compartilhamento do JVM costuma remover qualquer isolamento restante da camada de infraestrutura, exigindo que os próprios aplicativos de nível superior façam o isolamento. Este artigo apresenta o recurso de vários proprietários disponível para teste no Java 8 beta mais recente da IBM (consulte Recursos). Esse recurso permite que as implementações obtenham as vantagens do compartilhamento de JVM enquanto preserva um isolamento melhor que o alcançado com um compartilhamento de JVM tradicional.

Os benefícios e os custos do JVM de vários proprietários

O principal benefício do uso do JVM de vários proprietários é que as implementações evitam o consumo de memória normalmente associado ao uso de diversos JVMs padrão. Esse gasto adicional tem várias causas:

  • O heap Java consome centenas de megabytes de memória. Os objetos heap não podem ser compartilhados entre JVMs, mesmo os objetos idênticos. Além disso, os JVMs tendem a usar todo o heap alocado para eles, mesmo se a quantia máxima for por um curto período de tempo.
  • O compilador Just-in-time (JIT) consome dezenas de megabytes de memória, pois o código gerado é privado e consome memória. A produção do código gerado também toma ciclos significativos do processador, tirando tempo de outros aplicativos.
  • Os artefatos internos para classes consomem memória (muitos deles existem em todos os aplicativos, como string e hashtable ). Há uma instância de cada um desses artefatos em cada JVM.
  • Por padrão, todo JVM possui um encadeamento auxiliar coletor de lixo por núcleo, além de diversos encadeamentos de compilação. A atividade de compilação ou coleta de lixo pode ocorrer simultaneamente em ou mais JVMs. Isso pode não ser ideal, pois os JVMs competirão pelo tempo do processador limitado.

Além de reduzir a memória e os custos de processamento, o JVM de vários proprietários também oferece melhor isolamento comparado à execução de diversos aplicativos em um único JVM tradicional.

Outro benefício é que, após o início do primeiro proprietário do JVM compartilhado, os aplicativos subsequentes exigem menos tempo para iniciar, pois o JVM já está operando. Os tempos de inicialização reduzidos são especialmente úteis para aplicativos de curta execução que costumam ser usados para script.

O custo principal do uso de JVM de vários proprietários é que os proprietários ficam menos isolados comparados à execução de diversos aplicativos em JVMs diferentes. Por exemplo, uma paralisação nativa no JV M de vários proprietários afeta todos os proprietários.

Além disso, o trabalho realizado pelo JVM para implementar as extensões de vários proprietários resulta em uma pequena taxa de desempenho. Entretanto, o impacto dessa ocorrência de desempenho reduz à medida que o número de proprietários aumenta, — pois isso evita que o processador e o custo de memória executem diversos JVMs no mesmo sistema.


Usando o JVM de vários proprietários

Para optar pelo compartilhamento de um tempo de execução com outros proprietários, o usuário do aplicativo insere um único argumento, -Xmt, à linha de comando durante a ativação do aplicativo. Por exemplo:

java -Xmt -jar one.jar

O resultado é que o aplicativo se comporta como se estivesse executando em um JVM dedicado (conforme as limitações descritas posteriormente neste artigo). Mas, na realidade, ele opera paralelamente a outros aplicativos. As extensões no JVM de vários proprietários possibilitam esse tipo de ativação e fornecem isolamento entre os proprietários que compartilham o JVM.

Quando um proprietário é ativado, o ativador do JVM localiza o daemon do JVM compartilhado existente (javad) ou o inicia, se necessário, como mostra a Figura 1:

Figura 1. Figura 1. Ativador do JVM localiza (e inicia, se necessário) o daemon do JVM compartilhado automaticamente

Quando um segundo proprietário for ativado, ele encontrará o daemon do JVM compartilhado existente e executará no JVM, como mostra a Figura 2:

Figura 2. Figure 2. Ativador do JVM localiza e se conecta ao daemon do JVM existente

Como resultado, uma cópia do código de autoinicialização comum aos dois proprietários fica no processo javad . Esse acordo permite que os proprietários compartilhem mais estruturas de tempo de execução.

É fácil executar aplicativos existentes usando o JVM de vários proprietários, pois são necessárias apenas mudanças limitadas à linha de comando.


Conquistando isolamento

Dois ou mais aplicativos que executem no mesmo JVM (convencional) não costumam estar isolados entre si. A atividade de cada aplicativo afetaria o outro. Além disso, os dados que podem ser compartilhados pelos campos estáticos ficariam acessíveis para todos os aplicativos. O JVM de vários proprietários lida com esses problemas de duas formas: isolamento de campo estático e restrições de recursos.

Isolamento de campo estático

No JVM de vários, as partes invariáveis de classes são compartilhadas entre os proprietários. Essas partes incluem o código compilado para os métodos, as estruturas de dados usadas pelo JVM e outros artefatos semelhantes. Esse compartilhamento resulta em economias de memória, pois as cópias individuais que existiriam se houvesse diversos JVMs são desnecessárias. Entretanto, o JVM de vários proprietários dá uma cópia dos campos estáticos a cada proprietário. Por causa do isolamento de campo estático — e do fato de cada proprietário poder acessar, geralmente, as instâncias dos objetos que criaram, — cada proprietário pode acessar apenas os dados associados a ele. Isso resulta em isolamento de dados entre os proprietários.

Restrições de recursos: lidando com mau comportamento

Em um mundo perfeito, os proprietários cooperariam e usariam recursos compartilhados em forma adequada. No entanto, pode haver erros e comportamento malicioso nesse mundo imperfeito. O JVM de vários proprietários oferece controles que podem configurados para limitar as atitudes inadequadas de um proprietário e o mau uso dos recursos para não afetar outros proprietários. Os valores que podem ser controlados são:

  • Tempo do processador
  • Tamanho de heap
  • Contagem de encadeamento
  • E/S de arquivo: largura da banda de leitura e escrita
  • E/S de soquete: largura da banda de leitura e escrita

Esses controles podem ser especificados na linha de comando -Xmt . Por exemplo:

  • -Xlimit:cpu=10-30 (10% mínimo de CPU, 30% máximo)
  • -Xlimit:cpu=30 (30% máximo de CPU)
  • -Xlimit:netIO=20M (largura da banda máxima de 20 Mbps)
  • -Xms8m-Xmx64m (heap inicial de 8 MB, 64 MB máximo

A documentação do Java 8 inclui informações sobre todas as opções disponíveis (consulte Recursos).


Desempenho e área de cobertura

Como um teste para comparar o desempenho do aplicativo e a área de cobertura da memória em JVMs não compartilhadas e de vários usuários, adicionamos aplicativos à configuração de cada JVM até a troca do sistema. (Quando ele trocou, consideramos que o sistema estava "cheio".) No caso não compartilhado, executamos o aplicativo em um JVM separado e iniciamos um novo JVM para cada aplicativo adicional. No caso de vários proprietários, executamos o aplicativo como outro proprietário no JVM único de vários proprietários.

As tabelas 1 e 2 mostram os resultados encontrados usando uma máquina com 1 GB de memória e uma JVM de 64-bit (as JVM compactadas de referência com a política de coleta de lixo balanceada em todos os casos). A coluna "Ajuste manual" nas duas tabelas mostra os resultados da JVM comum depois que ajustamos manualmente as opções da linha de comando para tentar atingir a melhor densidade possível (Tabela 1) ou tempos de inicialização (Tabela 2). ). A coluna Padrão mostra os resultados do JVM comum com as opções padrão.

O JVM de vários proprietários atingiu 1,2x a 4,9x vezes a densidade do JVM não compartilhado, — dependendo do aplicativo, — como mostra a Tabela 1:

Tablela 1. Tabela 1. Número máximo de aplicativos simultâneos
AplicativosDescriçãoVários proprietáriosAjuste manualPadrãoMelhoria com JVM de vários proprietários
Hello World Imprimir "HelloWorld" e, depois, suspender 30973634,2X a 4.9X
Jettyiniciar Jetty e esperar solicitações34-181,9X
TomcatIniciar Tomcat e esperar solicitações28-132,1X
JRubyIniciar JRuby e esperar solicitações3226151,2X a 2,1X

O aumento da densidade é resultado do compartilhamento dos artefatos fundamentais, incluindo:

  • Classes artefatos relacionados carregados pela autoinicialização e os carregadores de classe de extensões, o objeto Class de heap de cada classe carregada e os objetos de heap que podem ser compartilhados facilmente pelos proprietários (por exemplo, Strings internas).
  • Código compilado por JIT e metadados para classes compiladas por JIT.
  • Heap: um proprietário pode usar espaço disponível no heap quando ele não for solicitado pelos outros.

A Tabela 2 mostra que encontramos médias de tempos de inicialização 1,2x a 6x mais rápidas com o JVM de vários proprietários:

Tablela 2. Tabela 2. Tempos de inicialização (primeiro/média)
AplicativosDescriçãoVários proprietáriosAjuste manualPadrãoMelhoria com JVM de vários proprietários
Hello WorldImprimir "HelloWorld" e, depois, suspender 5.709/138 ms514/400 ms3.361/460 ms3,3X
Jettyiniciar Jetty e esperar solicitações7.478/2.116 ms-6.296/1.2624 ms6X
TomcatIniciar Tomcat e esperar solicitações9.333/6.005 ms-7.802/7.432 ms1,2X
JRubyIniciar JRuby e esperar solicitações12.391/3.277 ms14.847/4.101 ms7.849/6.058 ms1,25X a 1,8X

Na Tabela 2, é possível ver que o tempo de inicialização da primeira instância do aplicativo geralmente é menor no JVM de vários usuários que no padrão. Esse resultado é esperado, pois a primeira instância incorre em alguns atrasos de inicialização adicionais por causa do comprimento maior do caminho causado pelas extensões multitenancy. O tempo de inicialização das instâncias subsequentes é consistentemente melhor para o JVM de vários proprietários.

Esses primeiros resultados foram obtidos com JVMs de desenvolvimento. É possível obter mais melhorias. Além disso, esses exemplos não são considerados no compartilhamento que pode ocorrer quando os aplicativos precisam de recursos em momentos diferentes. Em um JVM comum, a área de cobertura da memória de cada JVM tende a aumentar em direção ao limite que exige ao longo do tempo de vida. No JVM padrão, grande parte dessa área de cobertura não é compartilhada. Com o JVM de vários proprietários, se os requisitos do recurso não se sobrepuserem, a memória do heap e os artefatos nativos podem ser compartilhados com mais facilidade.


Limitações

Um objetivo do JVM de vários proprietários é poder executar todos os aplicativos Java sem modificações. Atualmente, isso não é possível por causa das limitações que as especificações Java impõem e das limitações de nossa implementação atual. As principais limitações conhecidas são:

  • Java Native Interface (JNI) nativos: o JVM não fornece isolamento para os JNI nativos. Os aplicativos com JNI nativos fornecidos pelos usuários podem não ser seguros para executar com o JVM de vários usuários. Esses aplicativos podem afetar a operação do JVM geral e acessar dados de outros proprietários. Em casos exigem a "confiança" nos nativos (como middleware conhecido), o risco pode ser aceitável. Além disso, o sistema operacional permite que os processos de JVM compartilhado carreguem apenas uma cópia de uma biblioteca compartilhada, que é onde os nativos estão localizados. Como resultado, os diversos proprietários não podem carregar os mesmos nativos se eles estiverem na mesma biblioteca compartilhada.
  • Java Virtual Machine Tool Interface (JVMTI): como as atividades de depuração e criação de perfil afetam todos os proprietários que compartilham o servidor do JVM, esses recursos não são suportados atualmente pelo JDK de vários proprietários. Essa é uma área que podemos desenvolver mais.
  • Programas GUI: as bibliotecas, como SWT, parecem manter um estado global na camada nativa. Por isso, não são suportadas no JDK de vários proprietários.

Conclusão

Este artigo apresentou o JVM de vários proprietários, o modo de usá-lo e os custos e benefícios desse uso. Esperamos ter despertado seu interesse em testar o beta e fornecer um feedback. Acreditamos que o JVM de vários proprietários pode fornecer benefício significativos para os ambientes adequados.

Recursos

Aprender

Obter produtos e tecnologias

Discutir

  • Participe da comunidade do developerWorks. Conecte-se com outros usuários do developerWorks enquanto explora os blogs, fóruns, grupos e wikis voltados para desenvolvedores.

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Cloud computing, Tecnologia Java
ArticleID=950990
ArticleTitle=Introdução à multitenancy do Java
publish-date=11012013