Tomcat Cluster con JSF

Tomcat Cluster con JSF

0. Índice de contenidos.

1. Entorno

Este tutorial está desarrollado usando el siguiente entorno:

  • Hardware: Portátil MacBook Pro 2Ghz Intel Core i7 (4 núcleos) 8Gb de RAM
  • Sistema Operativo: Mac OS X 10.7.2 (Lion)
  • Eclipse Indigo (Revisar tutorial de Alex para su instalación)
  • Apache Tomcat 7
  • Versión de java SDK 6 instalada en el sistema
  • Maven3 instalado y configurado en el sistema
  • Apache con mod_jk preconfigurado (se extenderá/modificará) (Consultar un ejemplo)

2. Introducción

A continuación veremos como realizar una configuración simple de un cluster tcp en Tomcat utilizando un Apache con mod_jk para el balanceo de peticiones.

3. Arquitectura

El objetivo de este tutorial será comprobar la escalabilidad y la réplica de sesión para una aplicación montada en JSF. La arquitectura de servidores será la siguiente:

arquitectura

En cada uno de los tomcat estará desplegada la misma aplicación con alguna variación en la vista para identificar el servidor que atiende a la llamada, como veremos en los siguientes apartados. Cabe decir, que todos los servidores estarán en la misma red.

La configuración de mod_jk será la siguiente:

workers.properties

uriworkermap.properties

La configuración de cada uno de los nodos será la misma salvo por el identificador del worker en el atributo jvmRoute del componente “Engine”:

server.xml-nodo1

server.xml-nodo2

Una vez realizados estos pasos, ya tenemos preparada la infraestructura a nivel de servidores que dejaremos iniciados.

4. Aplicación

Crearemos un nuevo proyecto maven3 con la siguiente estructura:

Estructura de proyecto maven

Ahora crearemos el pom.xml, en el cual nuestro objetivo será crear un paquete WAR para desplegarlo en Tomcat, y definir las dependencias con las librerías necesarias para trabajar con JSF:

El siguiente paso es la configuración de jsf en el web.xml, para que atienda todas las peticiones .jsf:

Ahora definiremos un ManagedBean con el scope session:

Y un listener para ver el ciclo de vida de la aplicación desde el que mostraremos el contenido de la sesión en cada petición:

Creamos la vista home.jsp

Por último la configuración de ambos en el faces-config.xml:

Cuando tengamos el proyecto con todas sus partes tan solo tenemos que ejecutar un mvn clean package que nos generará el archivo jsfcluster.war en la carpeta target.

5. Despliegue

Una vez generado el war tan solo tenemos que copiarlo en la ruta <apache_home>/webapps.

Cuando esté desplegado en ambos servidores modificamos la vista en la ruta <apache_home>/webapps/jsfcluster/home.jsp para cambiar las líneas que identificarán el nodo que atiende la petición (modificar la X por 1 ó 2 en cada caso):

6. Prueba de balanceo

Si todo ha ido bien, debemos estar en condiciones de realizar una peticion al apache con la siguiente url http://localhost/jsfcluster/home.jsf

Primera petición

Ahora rellenamos el campo de texto y realizamos peticiones consecutivas sobre el boton, verificando que se va variando de nodo en cada petición:

Segunda petición

Si revisamos los logs de ambos servidores, veremos que la sesion es la misma en cada caso:

Donde se identifican los managed beans (en nuestro caso texto) y su valor, y el arbol de componentes jsf (que debe ser exactamente el mismo en los dos nodos).

7. Problemas encontrados

Esta prueba es totalmente funcional con JSF, la versión 1.2_15 concretamente. La misma prueba la hemos realizado sobre JSF2 2.1.4 (implementación Sun Mojarra) sin que se realice correctamente la replica de la sesión en los dos nodos.

Desconocemos la causa de porque no funciona en JSF2, salvo si llevamos el arbol de componentes al cliente, con la consecuente penalización en las comunicaciones.

Animamos a nuestros lectores a que muestren su opinion y/o experiencias con otros servidores de aplicaciones o con Tomcat mismo para ver si descubrimos la posible causa del fallo.

8. Resultado

Aunque no hemos podido completar el ejemplo en jsf2 este ejemplo de cluster es válido para cualquier aplicación que esté preparada para trabajar en cluster, en el caso de tomcat, con los siguientes requerimientos:

  • Todos sus atributos de la sesión debe implementar el interfaz java.io.Serializable
  • Si se han definido las válvulas de costumbre cluster, asegúrese de que tiene la ReplicationValve definido así en el elemento de clústeres en server.xml
  • Si las instancias de Tomcat se está ejecutando en la misma máquina, asegúrese de que el tcpListenPort atributo es único para cada instancia, en la mayoría de los casos Tomcat es lo suficientemente inteligente como para resolver esto en su propia autodetección de puertos disponibles en el rango de 4000-4100
  • Asegúrese de que su web.xml tiene el elemento <distributable/>
  • Asegúrese de que todos los nodos tienen el mismo tiempo y la sincronización con el servicio NTP!

9. Conclusiones

Como comentaba en el anterior punto, este ejemplo es extrapolable a otro tipo de aplicaciones, ya que es la configuración básica de un tomcat en cluster con replicación de sesión.

Cualquier duda o sugerencia podeis comentarlo.

Saludos.