En un entorno de alta disponibilidad se desea tener una configuración mínima de 2 servidores web (pongamos Apache) balanceados con una capa previa con un Cisco CSS, o gastando un poco más de dinero con un F5 BigIP, un A10 Networks AX Series o el módulo Cisco ACE. Con esto solucionamos bien el primer nivel de balanceo, el frontend.

En algunas infraestructuras podemos encontrar un balanceo de segundo nivel, entre la capa de frontend y la de aplicación. Si el presupuesto ya no da más de sí podemos aprovecharnos del potente mod_jk. Éste conector entre Apache y Tomcat permite configurar opciones de balanceo por ‘peso’ (factor de prioridad), aunque tampoco podemos pedirle grandes virguerías. Es efectivo, mantiene las sesiones abiertas y si paramos un tomcat el usuario pasa a cualquiera de los otros tomcats disponibles.

Aunque no he probado todas las posibilidades ni indagado a fondo, la experiencia me dice que suele pasar más sesiones sobre el primer tomcat configurado, con lo que hasta que no encuentre el ‘error’ (o quizás es por las versiones que uso) suelo alterar el orden de los tomcats en los Apaches (o sea, Apache1 balancea sobre Tomcat1 y Tomcat2… y Apache2 balancea sobre Tomcat2 y Tomcat1) y así todos reciben más o menos la misma chicha.

A continuación los elementos de configuración tal y como yo los conozco, así que si hay dudas o algo no acaba de funcionar id a la documentación oficial:

  • Cargar el módulo (tenemos que haberlo descargado o compilado previamente y haberlo dejado en el directorio de módulos de Apache)

LoadModule jk_module modules/mod_jk.so

  • Cargaremos la configuración de mod_jk

<IfModule mod_jk.c>
Include conf/mod_jk.conf
</IfModule>

  • El archivo mod_jk.conf contiene la configuración básica tipo logs y otras opciones, además de definir los puntos de montaje de las aplicaciones y hacia qué worker mandará la petición:

JkWorkersFile conf/workers.properties
JkLogFile logs/jk.log
JkLogLevel error
# JkLogFile “|TIME=`date +%Y%m%d`;/opt/apache/bin/rotatelogs /opt/apache/logs/mod_jk.log.${TIME} 100M”
# JkLogLevel info

JRewriteRule ^/aplicacion$ /aplicacion/ [R=301,L]
JkMount /aplicacion/* tomapli
JRewriteRule ^/otra_aplicacion$ /otra_aplicacion/ [R=301,L]
JkMount /otra_aplicacion/* tomotra

  • Y qué son los workers? Es el recurso que va a recibir la petición… se podría haber configurado en el mismo archivo pero por limpieza lo ponemos en el workers.properties… ya se sabe, los currantes lejos del fichero ‘jefe’. Aquí como ejemplo definiremos un Tomcat para la aplicacion1 y luego dos tomcats en balanceo para la aplicacion2. Los ‘workers’ deben aparecer en la lista de worker.list:

worker.list=tomapli,tomotra1,tomotra2

# Aplicacion
############################
worker.tomapli.port=11009
worker.tomapli.host=10.10.10.113
worker.tomapli.type=ajp13
worker.tomapli.lbfactor=1
worker.tomapli.socket_timeout=300
worker.tomapli.socket_keepalive=1

# La otra
############################
worker.tomotra1.port=12009
worker.tomotra1.host=10.10.10.113
worker.tomotra1.type=ajp13
worker.tomotra1.lbfactor=1
worker.tomotra1.socket_timeout=300
worker.tomotra1.socket_keepalive=1

worker.tomotra2.port=12109
worker.tomotra2.host=10.10.10.113
worker.tomotra2.type=ajp13
worker.tomotra2.lbfactor=1
worker.tomotra2.socket_timeout=300
worker.tomotra2.socket_keepalive=1

worker.tomotra.balanced_workers=tomotra1,tomotra2
worker.tomotra.type=lb

  • En los servidores de aplicación sólo tendremos que asegurarnos de un par de detalles. Por un lado que cada tomcat, bajo el Service Catalina, el engine Catalina tenga el jvmRoute con el nombre que hemos especificado para ese worker:

(…)
<Service name=”Catalina”>
(…)
<Engine name=”Catalina” jvmRoute=”tomotra1″ defaultHost=”localhost” debug=”0″>

  • Y verificaremos que el jk2.properties no contenga nada ‘raro’ (aquí podemos forzar por ejemplo el channelSocket.port, aunque no hace falta).