Cluster en Glassfishv3 usando mod_jk para el balanceo de peticiones

1
12711

Cluster Glassfishv3 y mod_jk

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)
  • Oracle Glashfishv3
  • 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 de un cluster local con Glassfish utilizando un Apache con mod_jk para el balanceo de peticiones.

3. Arquitectura y configuración de mod_jk

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

La configuración de mod_jk será la siguiente:

workers.properties

# Define la lista de workers  que se usaran para mapear las peticiones
worker.list=loadbalancer,status
worker.maintain=2

# Configuración basica para todos los worker
worker.basic.type=ajp13
worker.basic.socket_timeout=1
worker.basic.connect_timeout=100
worker.basic.ping_mode=A
worker.basic.host=localhost
worker.basic.lbfactor=1

# Definimos el Nodo1
worker.node1.reference=worker.basic
worker.node1.port=8009

# Definimos el Nodo2
worker.node2.reference=worker.basic
worker.node1.port=8010

#Definimos el balanceo de carga
worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=node1,node2
worker.loadbalancer.sticky_session=false
worker.loadbalancer.retries=1
worker.status.type=status

uriworkermap.properties

# Contexto de nuestra aplicacion ejemplo
/jsfcluster=loadbalancer
/jsfcluster/*=loadbalancer

4. Instalación de glassfish y configuración de cluster

Lo primero que haremos será descargar una copia de glassfish desde la web: http://glassfish.java.net/es/downloads/3.0.1-final.html

Una vez descargado el archivo glassfish-3.0.1-unix-ml.sh (la versión para Mac), lo ejecutamos y seguiremos los siguientes pasos:

instalacion1

instalacion2

instalacion3

instalacion4

instalacion5

instalacion6

instalacion7

instalacion8

instalacion9

Ahora procederemos a iniciar la instancia creada de glashfish que utilizaremos como administradora del cluster.
Si no hemos realizado un update de glassfish, podemos realizarlo ejecutando <GLASHFISH_HOME>/bin/updatetool (donde <GLASHFISH_HOME> es la ruta configurada en el proceso de instalación), es bastante recomendable realizarlo para solucionar posibles problemas.
Abrimos un terminal, vamos a la ruta «<GLASHFISH_HOME>/glassfishv3/glassfish/bin» y ejecutamos «startserv» (si hemos updateado tendremos que ejecutar antes asadmin start-domain –upgrade en la misma ruta).

MacBook-Pro-de-Carlos:bin cleon$ ./startserv
26-dic-2011 19:16:13 com.sun.enterprise.admin.launcher.GFLauncherLogger info
INFO: L?nea de comandos de llamada de JVM:
/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/java
-cp
/Users/cleon/glassfishv3/glassfish/modules/glassfish.jar
-XX:+UnlockDiagnosticVMOptions
-XX:MaxPermSize=192m
-XX:NewRatio=2
-XX:+LogVMOutput
-XX:LogFile=/Users/cleon/glassfishv3/glassfish/domains/domain1/logs/jvm.log
-Xmx512m
-d32
-client
-javaagent:/Users/cleon/glassfishv3/glassfish/lib/monitor/flashlight-agent.jar
-Dfelix.fileinstall.disableConfigSave=false
-Djavax.net.ssl.keyStore=/Users/cleon/glassfishv3/glassfish/domains/domain1/config/keystore.jks
-Djava.awt.headless=true
-Dfelix.fileinstall.poll=5000
-Djava.endorsed.dirs=/Users/cleon/glassfishv3/glassfish/modules/endorsed:/Users/cleon/glassfishv3/glassfish/lib/endorsed
-Dfelix.fileinstall.bundles.startTransient=true
-Djavax.net.ssl.trustStore=/Users/cleon/glassfishv3/glassfish/domains/domain1/config/cacerts.jks
-Dcom.sun.enterprise.security.httpsOutboundKeyAlias=s1as
-DANTLR_USE_DIRECT_CLASS_LOADING=true
-Djava.security.auth.login.config=/Users/cleon/glassfishv3/glassfish/domains/domain1/config/login.conf
-Dgosh.args=--noshutdown -c noop=true
-Dosgi.shell.telnet.maxconn=1
-Djdbc.drivers=org.apache.derby.jdbc.ClientDriver
-Dfelix.fileinstall.dir=/Users/cleon/glassfishv3/glassfish/modules/autostart/
-Dosgi.shell.telnet.port=6666
-Djava.security.policy=/Users/cleon/glassfishv3/glassfish/domains/domain1/config/server.policy
-Dfelix.fileinstall.log.level=2
-Dosgi.shell.telnet.ip=127.0.0.1
-Dcom.sun.enterprise.config.config_environment_factory_class=com.sun.enterprise.config.serverbeans.AppserverConfigEnvironmentFactory
-Dcom.sun.aas.instanceRoot=/Users/cleon/glassfishv3/glassfish/domains/domain1
-Dcom.sun.aas.installRoot=/Users/cleon/glassfishv3/glassfish
-Djava.ext.dirs=/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/lib/ext:/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/jre/lib/ext:/Users/cleon/glassfishv3/glassfish/domains/domain1/lib/ext
-Dfelix.fileinstall.bundles.new.start=true
-Dfelix.fileinstall.debug=1
-Dorg.glassfish.web.rfc2109_cookie_names_enforced=false
-Djava.library.path=/Users/cleon/glassfishv3/glassfish/lib:/Users/cleon/glassfishv3/glassfish/bin:/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java
com.sun.enterprise.glassfish.bootstrap.ASMain
-domainname
domain1
-asadmin-args
--host,,,localhost,,,--port,,,4848,,,--secure=false,,,--terse=false,,,--echo=false,,,--interactive=true,,,start-domain,,,--verbose=true,,,--debug=false,,,--domaindir,,,/Users/cleon/glassfishv3/glassfish/domains,,,domain1
-instancename
server
-verbose
true
-debug
false
-asadmin-classpath
/Users/cleon/glassfishv3/glassfish/modules/admin-cli.jar
-asadmin-classname
com.sun.enterprise.admin.cli.AsadminMain
-upgrade
false
-type
DAS
-domaindir
/Users/cleon/glassfishv3/glassfish/domains/domain1
-read-stdin
true
26-dic-2011 19:16:13 com.sun.enterprise.admin.launcher.GFLauncherLogger info
INFO: Se ha iniciado correctamente en 12 mseg.
Launching GlassFish on Felix platform
26-dic-2011 19:16:15 com.sun.enterprise.server.logging.LogManagerService postConstruct
ADVERTENCIA: Record begin marker is not a proper value so using default.
26-dic-2011 19:16:15 com.sun.enterprise.server.logging.LogManagerService postConstruct
ADVERTENCIA: Record end marker is not a proper value so using default.
26-dic-2011 19:16:15 com.sun.enterprise.server.logging.LogManagerService postConstruct
ADVERTENCIA: Log Format field separator is not a character so using default.
26-dic-2011 19:16:15 com.sun.enterprise.server.logging.LogManagerService postConstruct
ADVERTENCIA: Date Format specified is wrong so using default.
[#|2011-12-26T19:16:15.474+0100|INFO|glassfish3.1.1|org.glassfish.ha.store.spi.BackingStoreFactoryRegistry|_ThreadID=10;_ThreadName=main;|Registered org.glassfish.ha.store.adapter.cache.ShoalBackingStoreProxy for persistence-type = replicated in BackingStoreFactoryRegistry|#]

[#|2011-12-26T19:16:15.706+0100|INFO|glassfish3.1.1|javax.enterprise.system.core.com.sun.enterprise.v3.admin.adapter|_ThreadID=10;_ThreadName=main;|The Admin Console is already installed, but not yet loaded.|#]

[#|2011-12-26T19:16:15.722+0100|INFO|glassfish3.1.1|javax.enterprise.system.core.com.sun.enterprise.v3.services.impl|_ThreadID=12;_ThreadName=Grizzly-kernel-thread(1);|Grizzly Framework 1.9.36 started in: 73ms - bound to [0.0.0.0:7676]|#]

[#|2011-12-26T19:16:15.722+0100|INFO|glassfish3.1.1|javax.enterprise.system.core.com.sun.enterprise.v3.services.impl|_ThreadID=14;_ThreadName=Grizzly-kernel-thread(1);|Grizzly Framework 1.9.36 started in: 90ms - bound to [0.0.0.0:4848]|#]

[#|2011-12-26T19:16:15.722+0100|INFO|glassfish3.1.1|javax.enterprise.system.core.com.sun.enterprise.v3.services.impl|_ThreadID=11;_ThreadName=Grizzly-kernel-thread(1);|Grizzly Framework 1.9.36 started in: 80ms - bound to [0.0.0.0:3700]|#]

[#|2011-12-26T19:16:15.723+0100|INFO|glassfish3.1.1|javax.enterprise.system.core.com.sun.enterprise.v3.services.impl|_ThreadID=15;_ThreadName=Grizzly-kernel-thread(1);|Grizzly Framework 1.9.36 started in: 114ms - bound to [0.0.0.0:8080]|#]

[#|2011-12-26T19:16:15.722+0100|INFO|glassfish3.1.1|javax.enterprise.system.core.com.sun.enterprise.v3.services.impl|_ThreadID=13;_ThreadName=Grizzly-kernel-thread(1);|Grizzly Framework 1.9.36 started in: 95ms - bound to [0.0.0.0:8181]|#]

[#|2011-12-26T19:16:15.758+0100|INFO|glassfish3.1.1|javax.enterprise.system.core.com.sun.enterprise.v3.server|_ThreadID=10;_ThreadName=main;|GlassFish Server Open Source Edition 3.1.1 (12) tiempo de inicio: Felix (1.101ms), servicios de inicio(508ms), total(1.609ms)|#]

[#|2011-12-26T19:16:15.969+0100|INFO|glassfish3.1.1|javax.enterprise.system.tools.admin.org.glassfish.server|_ThreadID=16;_ThreadName=Thread-24;|JMXStartupService: Started JMXConnector, JMXService URL = service:jmx:rmi://XX.XX.XX.XX:8686/jndi/rmi://XX.XX.XX.XX:8686/jmxrmi|#]

[#|2011-12-26T19:16:16.450+0100|INFO|glassfish3.1.1|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=17;_ThreadName=Gogo shell;|____________________________
Welcome to Apache Felix Gogo

|#]

Abrimos otra consola en la misma ruta y ejecutamos el comando «asadmin».

MacBook-Pro-de-Carlos:bin cleon$ ./asadmin
Utilice "exit" para salir y "help" para obtener ayuda en l?nea.

El primer paso será crear el cluster, al que llamaremos «cluster»:

asadmin> create-cluster cluster
El comando create-cluster se ha ejecutado correctamente.

Después creamos los dos nodos que compondrán el cluster, «node1» y «node2»:

asadmin> create-local-instance --cluster cluster node1
Rendezvoused with DAS on localhost:4848.
Asignaciones de puerto para instancia de servidor node1: 
JMX_SYSTEM_CONNECTOR_PORT=28686
JMS_PROVIDER_PORT=27676
HTTP_LISTENER_PORT=28080
ASADMIN_LISTENER_PORT=24848
JAVA_DEBUGGER_PORT=29009
IIOP_SSL_LISTENER_PORT=23820
IIOP_LISTENER_PORT=23700
OSGI_SHELL_TELNET_PORT=26666
HTTP_SSL_LISTENER_PORT=28181
IIOP_SSL_MUTUALAUTH_PORT=23920
El comando create-local-instance se ha ejecutado correctamente.
asadmin> create-local-instance --cluster cluster node2
Rendezvoused with DAS on localhost:4848.
Using DAS host localhost and port 4848 from existing das.properties for node
localhost-domain1. To use a different DAS, create a new node using create-node-ssh or
create-node-config. Create the instance with the new node and correct
host and port:
asadmin --host das_host --port das_port create-local-instance --node node_name instance_name.
Asignaciones de puerto para instancia de servidor node2: 
JMX_SYSTEM_CONNECTOR_PORT=28687
JMS_PROVIDER_PORT=27677
HTTP_LISTENER_PORT=28081
ASADMIN_LISTENER_PORT=24849
JAVA_DEBUGGER_PORT=29010
IIOP_SSL_LISTENER_PORT=23821
IIOP_LISTENER_PORT=23701
OSGI_SHELL_TELNET_PORT=26667
HTTP_SSL_LISTENER_PORT=28182
IIOP_SSL_MUTUALAUTH_PORT=23921
El comando create-local-instance se ha ejecutado correctamente.

Ahora asociaremos dos propiedades genericas para cada nodo del cluster para su comunicación con el mod_jk (el nombre del nodo y el puerto):

asadmin> create-jvm-options --target cluster "-DjvmRoute=\\${AJP_INSTANCE_NAME}"
Se han creado 1 opciones
El comando create-jvm-options se ha ejecutado correctamente.
asadmin> create-jvm-options --target cluster "-Dcom.sun.enterprise.web.connector.enableJK=\\${AJP_PORT}"
Se han creado 1 opciones
El comando create-jvm-options se ha ejecutado correctamente.

Ahora establecemos las dos propiedades para cada nodo del cluster:

asadmin> create-system-properties --target node1 AJP_INSTANCE_NAME=node1
El comando create-system-properties se ha ejecutado correctamente.
asadmin> create-system-properties --target node2 AJP_INSTANCE_NAME=node2
El comando create-system-properties se ha ejecutado correctamente.
asadmin> create-system-properties --target node1 AJP_PORT=8009
El comando create-system-properties se ha ejecutado correctamente.
asadmin> create-system-properties --target node2 AJP_PORT=8010
El comando create-system-properties se ha ejecutado correctamente.

Iniciamos el cluster:

asadmin> start-cluster cluster
El comando start-cluster se ha ejecutado correctamente.

Una vez realizados estos pasos, ya tenemos el cluster configurado para atender peticiones. Si cargamos la instancia de administración: http://localhost:4848/common/index.jsf logandonos con las credenciales
introducidas en la instalación, podemos ver toda la configuración del cluster introducida.
Los pasos anteriormente mencionados tambien los podriamos haber hecho mediante la herramienta de administración web, pero he optado por utilizar el comando asadmin ya que es mas potente.

cluster1

cluster2

cluster3

Propiedades nodo1

Propiedades nodo2

5. Aplicación

Crearemos un nuevo proyecto maven3 con la siguiente estructura (es la misma aplicación que utilizamos en el tutorial de clustering con Tomcat http://www.adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=tomcat7clusterjsf):

Estructura de proyecto maven

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

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.autentia</groupId>
	<artifactId>jsfcluster</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<name>jsfcluster</name>
	<description>Pruebas de clustering con jsf</description>

	<build>
		<finalName>${project.artifactId}</finalName>
		<plugins>
			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<dependencies>
		<dependency>
			<groupId>javax.faces</groupId>
			<artifactId>jsf-api</artifactId>
			<version>1.2_15</version>
		</dependency>

		<dependency>
			<groupId>javax.faces</groupId>
			<artifactId>jsf-impl</artifactId>
			<version>1.2_15</version>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.1</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
		<dependency>
			<groupId>javax.el</groupId>
			<artifactId>el-api</artifactId>
			<version>2.2</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>
	</dependencies>
</project>

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

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  <display-name>jsfcluster</display-name>
  <welcome-file-list>
    <welcome-file>home.jsf</welcome-file>
  </welcome-file-list>
  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.jsf</url-pattern>
  </servlet-mapping>
  <distributable/>
</web-app>

Ahora definiremos un ManagedBean con el scope session:

package com.autentia.jsfcluster.beans;

import java.io.Serializable;
/**
 * @author cleon
 *
 */
public class Texto implements Serializable {
	private static final long serialVersionUID = -330458269625644065L;
	private String texto;
	public Texto() {
	}
	public String getTexto() {
		return texto;
	}
	public void setTexto(String texto) {
		this.texto = texto;
	}
	
}

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:

package com.autentia.jsfcluster.listener;

import java.util.Enumeration;

import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.builder.ToStringBuilder;

/**
 * @author cleon
 *
 */
public class ListenerPhase implements PhaseListener {
	private static final long serialVersionUID = 1L;

	@Override
	public void afterPhase(PhaseEvent pe) {}

	@Override
	public void beforePhase(PhaseEvent pe) {
		System.out.println("POST-FASE: " + pe.getPhaseId());
		if (pe.getPhaseId() == PhaseId.RESTORE_VIEW){
			HttpSession session = (HttpSession)pe.getFacesContext().getExternalContext().getSession(false);
			if (session!=null){
				Enumeration<String> atributos = session.getAttributeNames();
				String nombreAtributo = "";
				System.out.println("Atributos en sesion: ");
				while (atributos.hasMoreElements()){
					nombreAtributo = atributos.nextElement();
					System.out.println("\tAtributo: " + nombreAtributo);
					Object atributo = session.getAttribute(nombreAtributo);
					System.out.println("\tValor: " + ToStringBuilder.reflectionToString(atributo));
				}
			}else{
				System.out.println("La session es nula: " + session);
			}
		}
	}

	@Override
	public PhaseId getPhaseId() {
		return PhaseId.ANY_PHASE;
	}
}

Creamos la vista home.jsp

<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<f:view>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Pruebas con clustering jsf</title>
</head>
<body>
<h3>Pruebas con clustering:</h3>
<%
out.println("NODOX<br/>");
System.out.println("NODOX");
if ( session.isNew() ) { %>
    Sesion nueva:  
<%
out.println(session.getId());
} else { %>
    Sesion existente: 
<%
out.println(session.getId());
}%>
<br/>
<h:form>
<h:outputLabel value="Introduce un texto: " /><h:inputText label="texto" value="#{texto.texto}"></h:inputText><br/>
<h:commandButton label="Submit" value="Submit"/><br/>
El texto introducido es: ${texto.texto}
</h:form>
</body>
</html>
</f:view>

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

<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xi="http://www.w3.org/2001/XInclude"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
 <managed-bean>
  <managed-bean-name>texto</managed-bean-name>
  <managed-bean-class>com.autentia.jsfcluster.beans.Texto</managed-bean-class>
  <managed-bean-scope>session</managed-bean-scope>
 </managed-bean>
 <lifecycle>
  <phase-listener>com.autentia.jsfcluster.listener.ListenerPhase</phase-listener>
 </lifecycle>
</faces-config>

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.

6. Despliegue

Una vez generado el war lo desplegamos desde la herramienta de administración web, seleccionando el cluster, la pestaña Applications, botón Implementar:

Implementar

Seleccionamos nuestro archivo local:

Selección de archivo

Marcamos la casilla «Disponibilidad» para que tenga replicación de sesión (este parámetro en conjunto con <distributable/> del «web.xml» lo hacen posible), tambien asociaremos nuestro cluster como destino seleccionado (lo suele poner por defecto):

Disponibilidad y selección de despliegue

Selección de archivo

Y ya tenemos nuestra aplicación desplegada:

Aplicación

Cuando esté desplegado en ambos servidores modificamos la vista en la ruta «<GLASHFISH_HOME>/glassfishv3/glassfish/nodes/localhost-domain1/nodeX/applications/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):

out.println("NODOX<br/>");
System.out.println("NODOX");

7. 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

Tercera petición

Si revisamos los logs de ambos servidores («<GLASHFISH_HOME>/glassfishv3/glassfish/nodes/localhost-domain1/nodeX/logs/server.log), veremos que la sesion es la misma en cada caso:

Atributos en sesion:
        Atributo: com.sun.faces.logicalViewMap
        Valor: com.sun.faces.util.LRUMap@ccc621[maxCapacity=15,accessOrder=true,threshold=16,loadFactor=1.0]
        Atributo: texto
        Valor: com.autentia.jsfcluster.beans.Texto@1e3bfb6[texto=Prueba Autentia!]
        Atributo: javax.faces.request.charset
        Valor: java.lang.String@13f5a2f[value={U,T,F,-,8},offset=0,count=5,hash=81070450]

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).

8. 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) realizando la replica de sesión correctamente (con algunos ajustes finos necesarios), contrariamente a lo que sucedía con Tomcat.
Según aporta Oracle en las notas de la release http://javaserverfaces.java.net/nonav/rlnotes/2.1.4/issues.html no está probada con Tomcat ni Jetty, con lo que esperamos que en un futuro las posteriores versiones estén
validadas en estos servidores.

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 glassfish en cluster con replicación de sesión. Por lo menos hemos podido comprobar que jsf2 funciona en clustering,
aunque sea sobre las plataformas Oracle.

Cualquier duda o sugerencia podeis comentarlo.

Saludos.

1 COMENTARIO

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad