Load Balancer para Tomcat com Apache e mod jk

De Wiki REDDES

Categoria:Infra-Estrutura

Tabla de contenidos

Configurando um load balancer com Apache e mod_jk

Introdução

Para aumentar a exploração dos recursos de infra-estrutura e melhorar a disponibilzação dos serviços fornecidos pela BIREME, estuda-se a possibilidade de um sistema de balaceamento de carga.

A elaboração deste texto foi feita a partir da experimentação de um sistema balanceamento de carga para dois Tomcats rodando na mesma máquina, conseguido com o uso do módulo mod_jk e o webserver Apache.

O seguinte é desejado desta implementação: * balanceamento de carga (load balance) * funcionamento do sistema em caso de uma da instancias falhar (failover)

Ambiente utilizado

A implementação deste sistema de balance aconteceu dentro de uma máquinha virtual, com Linux instalado para este propósito.

Ambiente Real

  • Petium D, 3GHZ
  • 2Gb de memória Ram
  • Windows XP
  • VMWare

Ambiente Virtual

  • 512Mb de memória RAM
  • Ubuntu Server 8.04
  • JDK 1.6.0_06

Material utilizado

  • Apache 2.2.8
  • Tomcat 6.0.16
  • mod_jk 1.2.26

Pré-requisitos

  • JDK 5
  • gcc
  • make

Instalação dos pré-requisitos

Para simplificar o processo, os pré-requisitos acima foram instalados através do gerenciador de pacotes disponível no Ubuntu. O nome dos pacotes para pré-requisitos são:

  • sun-java6-jdk
  • build-essential

Configuração do Ambiente

Configurar a seguinte variável de ambiente

JAVA_HOME=/LOCAL_DO_JDK


Instalação

Instalação do Apache

  • fazer download do Apache e decompactá-lo em uma pasta
  • criar a pasta onde se deseja a instalação
  • executar os seguintes comandos:
    • ./configure --prefix=/caminho/para/pasta/criada
    • make
    • make install

Instalação do Tomcat

  • fazer download do tomcat
  • criar duas pastas, onde cada uma tera uma instância
  • descompactar o arquivo nas duas pastas

Instalação do mod_jk

  • fazer download do mod_jk
  • descompactá-lo em local temporário
  • dentro da pasta native, rodar os seguinte comandos
    • ./configure --with-apxs=/LOCAL_DO_APACHE/bin/apxs --with-java-home=/PASTA_DO_JDK
    • (64 bits) ./configure CFLAGS='-arch x86_64' APXSLDFLAGS='-arch x86_64' --with-apxs=/LOCAL_DO_APACHE/bin/apxs
    • make
    • cp apache-2.0/mod_jk.so /LOCAL_DO_APACHE/modules/

Configuração

Configuração das instâncias de Tomcat

A Variável CATALINA_HOME

Em situações onde há somente uma instância de Tomcat na máquina, seria recomendável a criação de uma variável de ambiente chamada CATALINA_HOME, que apontaria para o diretório do Tomcat. Entretanto, serão dois Tomcats olhando para o mesmo diretório, o que irá causar falhas. Para este caso, o que deve ser feito é editar o arquivo catalina.sh, que fica dentro da pasta bin na instância Tomcat e adicionar a seguinte linha antes de qualquer outra instrução.

CATALINA_HOME=/CAMINHO_PARA_INSTANCIA_DESTE_TOMCAT

Isto deverá ser feito para cada instância de tomcat existente na computador.

Configuração do arquivo server.xml

Dentro da pasta conf de cada instância de Tomcat, existe um arquivo chamdado server.xml que deve alterado em função de cada instância. A primeira alteração consite em identificar cada Tomcat para que o balancer possa diferenciá-los. Para isso, devem ser seguidos alguns passos para cada instância, tal como a seguir.

Instância 1 que foi apelidada de "worker1":

  • Abra o arquivo server.xml
  • Localize a tag <Engine name="Catalina" defaultHost="localhost">
  • Altera a tag para <Engine name="Catalina" defaultHost="localhost" jvmRoute="worker1">

Instância 2 que foi apelidada de "worker2":

  • Abra o arquivo server.xml
  • Localize a tag <Engine name="Catalina" defaultHost="localhost">
  • Altera a tag para <Engine name="Catalina" defaultHost="localhost" jvmRoute="worker2">

No arquivo arquivo server.xml também são definidas as portas que o Tomcat irá monitorar esperando novas requisições. Para que não haja conflito, estes valores deverão ser alterados de forma que dois Tomcats não monitorem a mesma porta. O arquivo server.xml da instância 1 pode ser mantido, mas o da instância 2 deve ser altera, podendo ser feito através destes passos:

Instância 2:

  • Passo 1:
    • Localizar a tag <server port="8005" shutdown="SHUTDOWN">
    • Trocar por <server port="9005" shutdown="SHUTDOWN">
  • Passo 2:
    • Localizar a tag <Connector port="8080">
    • Trocar por <Connector port="9080">
  • Passo 3:
    • Localizar a tag <Connector port="8009" protocol="AJP/1.3" redirectPort="8443">
    • Trocar por <Connector port="9009" protocol="AJP/1.3" redirectPort="9443">

OBS.: Caso houvesse mais portas no arquivo server.xml, estas deveriam ser também alteradas.

Configuração do Apache

Para o mod_jk ser funcional no Apache, algumas linhas devem ser alteradas no arguivo httpd.conf, que na maioria das vezes encontra-se dentro do diretório conf. Para não desorganizar as configurações existentes do apache, sugere-se que um arquivo httpd-tomcat-balancer.conf seja criado e depois incluido no arquivo httpd.conf.

Um arquivo chamado workers.properties também deve ser criado e configurado dentro do diretório conf do Apache. Este arquivo configura as instancias de Tomcat que o balancer do mod_jk irá cuidar.

O httpd.conf e o httpd-tomcat-balancer.conf

Primeiro deve-se criar no diretório conf, um arquivo chamado httpd-tomcat-balancer.conf. Este arquivo deverá dizer ao Apache: que o módulo mod_jk deve ser carregado; aonde está o arquivo workers.properties; que endereço está associado ao balancer.

O seguinte código ilustra uma configuração funcional para o httpd-tomcat-balancer.conf.

# >> INICIO DO ARQUIVO DE CONFIGURAÇÃO <<
# Carrega o mod_jk no Apache
LoadModule jk_module modules/mod_jk.so

# Diz aonde a configuração do balancer
JkWorkersFile conf/workers.properties

# Diz aonde o mod_jk gravará Logs
JkLogFile /opt/apache-2.2.8/logs/mod_jk.log

# Diz o quão detalhado deve ser o Log
JkLogLevel info

# Especifica o forma das mensagens para gravação do Log
JkLogStampFormat "[%a %b %d %H:%M%:%S %Y]"

# Virtual Hosts para o mod_jk
<VirtualHost *>
	ServerName 172.27.0.213

# Qual o endereço para o balancer
  JkMount /*.jsp balancer
  
# Endereço para monitor do mod_jk
  JkMount /jkstatus
</VirtualHost>
# >> FIM DO ARQUIVO DE CONFIGURAÇÃO <<

No final arquivo httpd.conf, deve ser incluído o seguinte techo.

Include conf/httpd-tomcat-balancer.conf

O workers.properties

Este arquivo irá declarar a instâncias de Tomcat e o balancer. Para o entendimento do trecho abaixo, deve ser assumido que o nome "worker1" é a referência para uma instância de Tomcat e "worker2" para a segunda instância de Tomcat. O arquivo abaixo ilustra a configuração para este arquivo.

	
# >> INICIO DO ARQUIVO DE CONFIGURAÇÃO <<
ps=/

# coloca como 'worker' as duas referencia criadas
worker.list=balancer,status

# configuração para acesso ao worker1
worker.worker1.type=ajp13
worker.worker1.host=localhost
worker.worker1.port=8009
worker.worker1.lbfactor=5

# configuração para acesso ao worker2
worker.worker2.type=ajp13
worker.worker2.host=localhost
worker.worker2.port=9009
worker.worker2.lbfactor=5

# criando o balancer (lb = load balancer)
worker.balancer.type=lb
worker.balanced_workers=worker1,worker2

# criando o monitor do balancer
worker.status.type=status
# >> FIM DO ARQUIVO DE CONFIGURAÇÃO <<

Testes

Criar duas páginas teste

Para ver se o balancer está funcionando corretamente, pode-se fazer um experimento construindo duas páginas 'index.jsp', conforme declarada no arquivo 'httpd-tomcat-balancer.conf', que sejam distintas. Estas páginas podem ser colocadas dentro da pasta Webapp existente nos Tomcats. Abaixo, sugestão de dois arquivos 'index.jsp', um para cada Tomcat.

Para instância 1

<html>
	<body bgcolor='blue'>
		<h1>Tomcat 1</h1>
		<%= request.getSession().getId(); %>
	</body>
</html>
# Fim

Para instância 2

<html>
	<body bgcolor='red'>
		<h1>Tomcat 2</h1>
		<%= request.getSession().getId(); %>
	</body>
</html>
# Fim

Copidos os arquivos para as instâncias de Tomcat, deve-se ligar um navegador de internet e acessar o endereço do para o qual foi configurado o Apache e acessar o index.jsp.

	Exemplo:
		http://172.27.0.213/index.jsp

Apertando várias vezes a tecla de atualizar página, deve ser possível vizualizar duas página com a cor de fundo diferente.

Status

Caso as configurações deste texto sejam seguida, deve estar disponível uma área de monitoramento do balancer. Basta indicar o endereço do apache e acessar 'jkstatus'.

	Exemplo:
		http://172.27.0.213/jkstatus

Apache Benchmark (AB)

Sugere-se que o balancer seja testado também com o Benchmark do Apache, para que se tenha uma idéia da estabidade do sistema.

  • Primeiro:
  • Segundo:
    • executar: "./ab -n 2000 -c 50 http://172.27.0.213/index.jsp
    • parar uma das instâncias tomcat durante o os testes do ab
    • verificar número de falhas pelo ab
  • Terceiro:
    • alterar o 'lb_factor' de uma das instâncias no arquivo workers.properties
    • executar: "./ab -n 2000 -c 50 http://172.27.0.213/index.jsp
    • verificar número de falhas pelo ab

Resultados

Nas primeiras vezes que os teste foram executados, nenhum problema foi detectado. O 'failover' funcionou corretamente e a carga foi distruibuída igualmente para os dois servidores.

Cada teste deve ser executado várias vezes, considerando o ultima vez como mais relevante, mas não desconsirendo a primeira vez. Quando o servidor está ocioso, o Apache tem um número pequeno de threads esperando por requisições. Quando de disparam 2000 requisições por exemplo, o Apache levará um tempo para criar novas threads que possam tratar novas requisições. Logo, a criação de threads pode influenciar o tempo de resposta para as requisições. Se o servidor Apache estiver recebendo requisições continuamente, é provável que já existam um grande de número de threads esperando requisições, assim, é provável que o tempo de resposta seja reduzido em relação ao cenário anterior, pois não gasta-se tempo criando threads.

Resultado do AB para o primeiro teste

>> 	Server Software:        Apache/2.2.8
>> 	Server Hostname:        172.27.0.213
>> 	Server Port:            80
>> 	
>> 	Document Path:          /index.jsp
>> 	Document Length:        103 bytes
>> 	
>> 	Concurrency Level:      50
>> 	Time taken for tests:   16.687607 seconds
>> 	Complete requests:      2000
>> 	Failed requests:        1000
>> 	   (Connect: 0, Length: 1000, Exceptions: 0)
>> 	Write errors:           0
>> 	Total transferred:      681000 bytes
>> 	HTML transferred:       207000 bytes
>> 	Requests per second:    119.85 [#/sec] (mean)
>> 	Time per request:       417.190 [ms] (mean)
>> 	Time per request:       8.344 [ms] (mean, across all concurrent requests)
>> 	Transfer rate:          39.85 [Kbytes/sec] received
>> 	
>> 	Connection Times (ms)
>> 	              min  mean[+/-sd] median   max
>> 	Connect:        0    0   3.8      0      15
>> 	Processing:   156  411  32.7    406     765
>> 	Waiting:      156  410  32.8    406     765
>> 	Total:        156  412  32.8    406     765
>> 	
>> 	Percentage of the requests served within a certain time (ms)
>> 	  50%    406
>> 	  66%    421
>> 	  75%    421
>> 	  80%    421
>> 	  90%    437
>> 	  95%    437
>> 	  98%    500
>> 	  99%    546
>> 	 100%    765 (longest request)

Resultado do AB para o segundo teste

>> 	Server Software:        Apache/2.2.8
>> 	Server Hostname:        172.27.0.213
>> 	Server Port:            80
>> 	
>> 	Document Path:          /index.jsp
>> 	Document Length:        104 bytes
>> 	
>> 	Concurrency Level:      50
>> 	Time taken for tests:   17.421987 seconds
>> 	Complete requests:      2000
>> 	Failed requests:        0
>> 	Write errors:           0
>> 	Total transferred:      682000 bytes
>> 	HTML transferred:       208000 bytes
>> 	Requests per second:    114.80 [#/sec] (mean)
>> 	Time per request:       435.550 [ms] (mean)
>> 	Time per request:       8.711 [ms] (mean, across all concurrent requests)
>> 	Transfer rate:          38.23 [Kbytes/sec] received
>> 	
>> 	Connection Times (ms)
>> 	              min  mean[+/-sd] median   max
>> 	Connect:        0    0   3.8      0      15
>> 	Processing:   109  429  72.2    406     984
>> 	Waiting:      109  429  72.2    406     984
>> 	Total:        109  430  72.2    406     984
>> 	
>> 	Percentage of the requests served within a certain time (ms)
>> 	  50%    406
>> 	  66%    421
>> 	  75%    421
>> 	  80%    484
>> 	  90%    531
>> 	  95%    562
>> 	  98%    609
>> 	  99%    625
>> 	 100%    984 (longest request)

Problemas Conhecidos

Apache não redireciona para Tomcat

Verificar se os Workers realmente estão rodando nas portas especificadas nos arquivos de configuração. Caso um Worker tente iniciar em uma porta ocupada, um aviso será jogado no arquivo de log catalina.out e uma nova porta será alocada para esta inicialização, invalidando todas as configurações feitas. Por exemplo: uma VMWare ocupa a porta 8009, então o worker do Tomcat não conseguirá utilizar esta porta e provavelmente usará a 8010 para iniciar o serviço.

Herramientas personales