Esse artigo faz parte da revista Java Magazine edição 29. Clique aqui para ler todos os artigos desta edição

esse aqui">Clique aqui para ler esse artigo em PDF.imagem_pdf.jpg

Java Livre

Clusters Web com Tomcat

Distribuição de Carga e Alta Disponibilidade

Aprenda a configurar vários servidores Tomcat como um cluster, de modo a atender mais usuários e ocultar deles panes em algum dos servidores

Fernando Lozano

Cluster é um dos termos mais usados em toda a informática, identificando qualquer configuração com vários computadores com o objetivo de fornecer maior capacidade bruta de trabalho, e algum nível de tolerância à falhas. Neste artigo estamos interessados em um tipo bem específico de cluster – voltado a aplicações web J2EE.

Os exemplos serão apresentados utilizando o Tomcat 5 (5.5.x ou 5.0.x), mas todos os conceitos serão válidos para outros containers web, livres e proprietários. Não fará diferença usar o J2SE 1.4.2 ou 5.0, desde que seja utilizada a versão do Tomcat correspondente ao seu Java (5.0.x com o J2SE 1.4.x; 5.5 com o J2SE 5.0).

E o melhor: suas aplicações web, se desenvolvidas conforme as recomendações do J2EE e algumas boas práticas, não vão precisar sofrer qualquer modificação para se adequarem às configurações de cluster apresentadas. No entanto, muitas aplicações ainda são desenvolvidas sem seguir essas recomendações, podendo não funcionar corretamente num cluster (também podendo apresentar problemas em outras situações).

Para mais informações sobre a forma “correta” de desenvolver aplicações web J2EE, consulte o quadro “Desenvolvendo para clusters”. Para conhecer alguns conceitos de clusters e a terminologia relacionada usada nesse artigo consulte o quadro “Conceitos de clusters web etc.”.

Este artigo assume que que o leitor já tem algum conhecimento prévio da instalação e configuração do Tomcat e do Apache, além de conhecimento de desenvolvimento de aplicações web. A instalação do Tomcat e Apache foi abordada antes nesta mesma coluna, na edição nº 6, e no artigo de Gabriel Esteves na edição nº 8. Fundamentos do desenvolvimento de aplicações web com o Tomcat, incluindo o uso de suas aplicações administrativas, foram apresentados nesta coluna nas edições nº 18, 19 e 20.

Preparação

A configuração será feita em duas etapas. Primeiro será criado um cluster que fornece apenas maior escalabilidade, dividindo a carga de trabalho entre vários servidores Tomcat. Depois será demonstrado como fornecer também tolerância a falhas, permitindo que um nó assuma de forma transparente os usuários que eram atendidos por outro nó que falhou.

Para que seja possível testar o ambiente de cluster, simulando vários usuários, o leitor irá necessitar de pelo menos dois navegadores web instalados em seu computador. Por exemplo, o Firefox e o Internet Explorer (IE) no Windows; ou um Firefox e um Konqueror no Linux.

Embora o ambiente de produção preferencial para clusters Tomcat sejam servidores Unix e Linux, a configuração é independente do sistema operacional. Particularmente, o leitor também poderá seguir os exemplos em qualquer versão do Windows a partir da 98.

Apenas a instalação do servidor web que atuará como balanceador será diferente em cada plataforma. Para os detalhes, consulte os quadros “Instalação do Apache e mod_jk em Linux”, “Instalação do Apache e mod_jk em Windows” e “Instalação do IIS com mod_jk no Windows”

Clusters Tomcat + Apache

Um cluster web é constituído por um balanceador de carga, que o usuário “enxerga” como sendo o servidor web que responde ao seu navegador, e um conjunto de servidores web (ou de containers web) que são efetivamente os nós do cluster.

Para balanceador, optamos pelo Servidor Web Apache 2.0. O quadro “Clusters web no J2EE” apresenta mais detalhes sobre a configuração genérica desse cluster e os seus requisitos. Neste artigo estamos focando numa implementação específica, aplicável em muitas situações típicas, utilizando os recursos do Tomcat.

A Figura 1 apresenta a arquitetura física do cluster que será construído. Um único servidor Apache, rodando o módulo mod_jk, atua como balanceador de carga para duas instâncias do Tomcat. Para construir a configuração deste artigo, será necessário, portanto, instalar um Apache e duas cópias do Tomcat em diretórios diferentes. Usuários Windows podem usar a versão do Apache nativa para seus sistemas.

Módulos e conectores

O mod_jk é um módulo de extensão para o Apache e outros servidores web, que permite sua integração a um container web Tomcat. Ele é baseado no protocolo AJP (Apache Java Protocol), que permite a um servidor web obter várias informações de gerenciamento do container. Apesar do AJP não ser parte oficial da plataforma J2EE, ele é um padrão de mercado, sendo utilizado por vários outros containers e extensões de servidores web.

Embora seja comum dizer que o Tomcat é um container web, esta afirmação não é muito precisa. O container web em si, chamado Catalina, é apenas um dos componentes que formam o Tomcat. Outros componentes são o compilador de páginas JSP, chamado Jasper (sem relação com o JasperReports), os vários conectores que gerenciam conexões de redes, e vários projetos do Jakarta Commons, como o DBCP para pools de conexões JDBC.

No lado do Tomcat, deve ser configurado e ativado o conector Jk, que recebe requisições AJP. Este conector é parte da instalação padrão do Tomcat desde suas primeiras versões. Com o conector Jk ativo, seria possível desligar a funcionalidade de servidor web embutida no Tomcat, fornecida pelo conector Coyote, porém é recomendável manter este conector para que seja possível acessar aplicações administrativas (Manager e Admin) em cada nó Tomcat de forma independente. O conector Coyote também nos permite validar o funcionamento individual de cada nó do cluster, e assim isolar problemas de configuração do balanceador.

Portas TCP e pacotes multicast

Será utilizado um único computador para montar o cluster, de modo que todos os leitores possam experimentar as configurações indicadas e validar suas aplicações. Por isso, temos que atribuir portas TCP diferentes para cada instalação do Tomcat. Será utilizado o endereço de loopback do TCP/IP (127.0.0.1). Assim o computador do leitor não necessitará estar ligado a uma rede.

Cada nó do cluster anuncia sua presença aos demais utilizando pacotes multicast. Um pacote multicast é endereçado a um subconjunto dos computadores presentes em rede local. Ele é diferente de pacotes unicast, endereçados a um único computador e de pacotes broadcast, endereçados a todos os computadores na rede. O uso do multicast facilita muito a manutenção do cluster, pois torna desnecessário se ter em cada nó uma lista dos endereços e portas dos demais nós. Além disso, com o uso de pacotes multicast, é consumida menos largura de banda do que se forem utilizados pacotes unicast ou broadcast.

O uso do multicast pode exigir configurações especiais do seu sistema operacional ou dos seus equipamentos de rede (switches e roteadores). Para leitores que venham a testar a configuração em Linux, recomendamos a consulta ao quadro “IP Multicast no Linux”.

Replicação de sessões

A replicação de sessões HTTP é a “alma” do cluster, pois é ela que permite que um nó do cluster assuma os usuários que estavam sendo atendidos por outro nó que falhou. Ela é realizada por conexões TCP diretas entre cada par de nós. Versões do Tomcat anteriores à 5.0 não traziam o suporte a esse recurso, que tinha de ser fornecido por um software externo como um servidor de aplicações JBoss usando o Tomcat como container. Várias soluções eram baseadas em bancos de dados relacionais ou mesmo arquivos compartilhados em rede para realizar a replicação das sessões.

Diferentemente da maioria dos produtos de terceiros[1], a replicação nativa do Tomcat é baseada em memória, não em armazenamento em disco ou em banco de dados. Além de ser mais leve e rápida, isso elimina um potencial ponto de falha no ambiente – afinal se o banco de dados utilizado para a replicação cair, morre o cluster. Mas nada impediria o uso dessas soluções com o Tomcat.

É possível acrescentar ou remover nós ao cluster a qualquer momento. Ao entrar no cluster, um novo nó detecta os demais pelos multicasts e requisita uma cópia inicial do estado de todas as sessões HTTP, antes de passar a aceitar requisições. Já se um nó cair (ou for desligado do cluster). Os demais nós também irão perceber que um deles não está mais enviando os multicasts (ou então que ele não responde na conexão de replicação) e irão parar de replicar com este nó. O balanceador também irá perceber que o nó falho não mais responde, e parar de encaminhar requisições a ele.

Para o balanceador, o acréscimo de um novo nó é igual à inicialização do cluster. Afinal, os vários nós não são inicializados exatamente ao mesmo tempo, então obrigatoriamente o cluster passa seus primeiros segundos de vida com apenas um nó, depois entra o segundo nó, e assim por diante.

Entretanto, a configuração do balanceador em geral tem que relacionar todos os nós que poderiam possivelmente fazem parte do cluster, então acrescentar um nó realmente novo exigiria atualizar a configuração do balanceador. Neste sentido, o Apache é uma boa opção, pois sua reinicialização é bem rápida, e em sistemas Linux ele pode ser reconfigurado sem reinicialização. Durante esta reinicialização ou reconfiguração há uma possibilidade remota de se perder algumas requisições de usuários, mas pode ser ignorada, pois não é maior do que a chance de se perder uma requisição devido ao congestionamento na própria rede.

Clusters para balanceamento de carga

A primeira versão do nosso cluster não terá recursos de tolerância à falhas. Ela penas permite que a carga de trabalho de usuários simultâneos seja distribuída entre vários Tomcats. Esta variação do cluster já era possível no Tomcat 4, e era criada da mesma forma como fazemos com a versão 5.0/5.5.

Como não há replicação de sessões HTTP, é necessário usar um artifício para que os dados das sessões do usuário não sejam “esquecidos”, por exemplo se a página anterior for atendida por outro nó do cluster. Usamos o recurso conhecido como sticky sessions (traduzindo livremente: “sessões duradouras”), cujo uso é a principal diferença entre um “balanceador genérico” e um balanceador específico para HTTP.

O recurso de sticky sessions consiste em se anexar ao identificador da sessão um sufixo que identifica o nó onde a sessão foi criada. O balanceador usa o sufixo para garantir que todas as requisições posteriores do usuário sejam encaminhadas ao mesmo nó do cluster. Se isso não for feito, a aplicação irá “esquecer” informações armazenadas anteriormente na sessão HTTP. Entretanto, uma falha no nó que contém a sessão do usuário irá obrigá-lo a iniciar uma nova sessão em outro nó do cluster. E se a aplicação usar controle de acesso, será necessário também um novo login.

Configuração do Apache e mod_jk para balanceamento de carga

A partir desse ponto, consideramos que o leitor já instalou o Tomcat, o Apache e o mod_jk (ou então o IIS/PWS e o ISAPI Redirector), seguindo os quadros que fornecem instruções específicas para seu sistema operacional. Em seguida vamos mostrar as instruções para a configuração do cluster.

Configuração do apache e do mod_jk

Uma instalação padrão do Apache 2.0 em Linux[2] contém a pasta conf.d, onde podem ser criados arquivos de configuração adicionais, contendo qualquer comando que seria válido no arquivo de configuração principal httpd.conf. A idéia com isso é facilitar a organização de configurações específicas de módulos do servidor e o teste de configurações alternativas.

Deve ser criado na pasta conf.d o arquivo jk.conf. A Listagem 1 apresenta seu conteúdo (note que alguns caminhos absolutos terão que ser transformados em caminhos relativos no Windows). A diretiva jkMount redireciona um padrão de URL recebido pelo Apache para ser processado pelo mod_jk, e enviado para um dos nós Tomcat. No caso, foi redirecionado o contexto /testacluster.

O contexto /jk, específico do mod_jk, gera uma página para monitorar o estado dos nós do cluster, por exemplo para saber quais estão ativos e a carga de trabalho em cada um. Estas requisições não serão enviadas para nenhum dos nós Tomcat, sendo respondidas pelo próprio mod_jk.

O cluster em si é definido pelo arquivo de configuração do mod_jk, chamado worker.properties e apresentado na Listagem 2. Observe a entrada balance_workers. Ela indica quais nós fazem parte do cluster. Depois é configurada a página de status, e por fim cada nó do cluster é configurado individualmente com seus parâmetros de conexão (no mínimo, o endereço IP e a porta TCP).

Os nomes utilizados para cada grupo de configurações (worker.cluster, worker.status, worker.no1 e worker.no2) podem ser modificados livremente, desde que seja mantido o prefixo worker. Mas é necessário indicar a propriedade worker.list, que indica quais configurações podem receber diretamente requisições redirecionadas pelas entradas JkMount na configuração do Apache.

É possível indicar, na configuração do mod_jk, um “peso” (weight) para cada nó do cluster. O peso é utilizado para indicar o quanto de carga de trabalho um nó é capaz de receber em relação aos outros. Por exemplo, se um nó tem peso 2 e o outro tem peso 1, a cada três requisições duas irão para o primeiro e uma para o segundo.

Configuração do Tomcat

Cada instalação do Tomcat deverá ter seu arquivo server.xml configurado conforme a Listagem 3. Note que o identificador do nó (jmvRoute) tem que ser consistente com o nome do nó na configuração do mod_jk, para que o recurso de sticky sessions funcione. Note também que cada servidor Tomcat deve indicar uma porta TCP diferente no elemento Server. Esta porta é usada unicamente para o shutdown do servidor. Então o servidor Tomcat com identificador no1 usa as portas 8105, 8180 e 8109 respectivamente para o desligamento do servidor, o conector Coyote (HTTP) e o conector Jk (AJP). Já o servidor no2 usa as portas 8205, 8280 e 8209.

Balanceando usuários versus requisições

Observe que esta configuração poderá não fazer um balanceamento perfeito da carga de trabalho. Por estar utilizando sticky sessions, ela irá balancear a criação de sessões, ou seja, os usuários e não as requisições individuais destes. Desse modo, a carga de trabalho real em cada servidor poderá ficar bastante desigual.

É possível configurar o mod_jk para fazer o balanceamento baseando-se na largura de banda consumida por cada nó, o que em teoria geraria uma utilização mais uniforme dos nós. Mais adiante, quando mostrarmos a configuração da replicação de sessões, será possível desligar o recurso de sticky sessions, de modo que serão balanceadas as requisições individuais.

Na verdade, não é possível determinar a priori qual configuração irá distribuir a carga de trabalho de modo mais homogêneo entre os nós do cluster. O ganho obtido por desligar sticky sessions ...

Quer ler esse conteúdo completo? Tenha acesso completo