Si hay algo en lo que Alfresco ha trabajado en cada una de las versiones que han visto la luz ha sido el tema de cluster y la comunicación entre los nodos. En las versiones 2.x con EHCache y un sistema de multicast que era bastante pobre, usando JGroups en la 3.x hasta llegar a la 4.2.x con Hazelcast.
Pero, ¿qué es Hazelcast?
Es según la propia página web oficial un “Open Source In-Memory Data Grid”, es decir, una plataforma para la distribución de datos de código abierto. Entre sus características podemos encontrar:
- Implementaciones distribuidas de Set, List, Map, Lock, MultiMap
- Mensajería distribuida P/S
- Soporte transaccional e integración JEE vía JCA
- Soporte encriptación a nivel de sockets
- Persistencia síncrona o asíncrona
- Clusterizado Sesión HTTP
- Discovery dinámico
- Monitorización JMX
- Escalado dinámico
- Particionado dinámico
- Fail-over dinámico
Como se puede ver, es una herramienta fantástica para cumplir las especificaciones de cluster que necesita Alfresco.
Las funciones de las que se sirve Alfresco y que son comunes a Hazelcast están:
- Compartir datos/estados entre varios servidores: como compartición sesión Web
- Cacheo distribuido de datos
- Comunicación segura entre servidores
- Particionado de datos en memoria
- Distribución de trabajo entre servidores
- Procesamiento paralelo
- Gestión fail-safe de datos
Además se lleva muy bien con Hibernate como caché de segundo nivel y con Spring.
¿Cómo configuramos el cluster de Alfresco 4.2.2?
Para configurar un sistema de cluster en Alfresco 4.2.2 es tan fácil como cuando se configuraba con EHCache o JGroups e incluso más todavía y eso sí, se comprueba la fiabilidad que tiene este producto integrado en Alfresco.
Hay que entender que aquí explico solamente como montar el cluster, es decir, que ambos nodos se comuniquen entre sí, un sistema completo de alta disponibilidad requiere de un balanceador ya sea hardware o software, un sistema de cluster en la base de datos, etc.
Lo primero que hay que hacer es quitar cualquier referencia a EHCache y JGroups antiguos, esto va orientado a sistemas que han ido siendo actualizados desde versiones antiguas principalmente:
Por ejemplo, el fichero que está dentro de {alfrescoRoot}/tomcat/shared/clases/alfresco/extensión:
ehcache-custom.xml
También en dicha localización (si existe) el fichero:
hazelcastConfig.xml
Este fichero se ha incluido ya dentro del fichero alfresco.war con lo que no hace falta.
Así como las siguientes propiedades que están dentro de {alfrescoRoot}/tomcat/shared/clases/alfresco-global.properties:
alfresco.cluster.name
alfresco.ehcache.rmi.hostname
alfresco.ehcache.rmi.port
alfresco.ehcache.rmi.remoteObjectPort
alfresco.jgroups.defaultProtocol
alfresco.jgroups.bind_address
alfresco.jgroups.bind_interface
alfresco.tcp.start_port
alfresco.tcp.initial_hosts
alfresco.tcp.port_range
alfresco.udp.mcast_addr
alfresco.udp.mcast_port
alfresco.udp.ip_ttl
filesystem.cluster.enabled
filesystem.cluster.configFile
Configuración del cluster para el repositorio
Por defecto si apuntamos dos instancias de Alfresco al mismo repositorio y base de datos, estos formarán de forma automática un grupo de repositorio, no obstante hay que realizar una pequeña configuración para que todo funcione correctamente.
Montar el repositorio de forma compartida y visible para todos los nodos, por ejemplo vía NAS o SAN a través de protocolo NFS.
Configurar el acceso a la base de datos para la misma base de datos en cada uno de los nodos.
Abrir el puerto 5701 TCP en el cortafuegos de los nodos para que puedan ser accesibles entre ellos.
Especificar correctamente la IP (sea en wildcard como por ejemplo 192.168.1.*) de la tarjeta de red del cluster:
alfresco.cluster.interface=192.168.1.101
Fijar la propiedad para activar Hazelcast en JMX
hazelcast.jxm=true
Y por razones de seguridad se debería fijar la contraseña con la siguiente propiedad:
alfresco.hazelcast.password=
Un ejemplo de la parte del fichero alfresco-global.properties para la configuración del cluster puede ser la siguiente:
alfresco.cluster.enabled=true
alfresco.cluster.interface=192.168.1.101
alfresco.hazelcast.password=clavehazelcast
alfresco.hazelcast.port=5701
alfresco.hazelcast.autoinc.port=false
alfresco.hazelcast.mancenter.enabled=false
alfresco.hazelcast.max.no.heartbeat.seconds=15
Una vez arrancada la primera instancia se puede observar un mensaje como el siguiente:
2014-06-30 22:38:36,148 INFO [cluster.core.ClusteringBootstrap] [localhost-startStop-1] Cluster started, name: MainRepository-fea9ebdf-04f3-495e-9456-cf43c24b8e91
2014-06-30 22:38:36,152 INFO [cluster.core.ClusteringBootstrap] [localhost-startStop-1] Current cluster members:
192.168.1.101:5701 (hostname: alfnode1.localdomain)
Finalmente al arrancar el segundo en este se observará lo siguiente:
2014-07-02 10:58:12,108 INFO [cluster.core.ClusteringBootstrap] [localhost-startStop-1] Cluster started, name: MainRepository-fea9ebdf-04f3-495e-9456-cf43c24b8e91
2014-07-02 10:58:12,111 INFO [cluster.core.ClusteringBootstrap] [localhost-startStop-1] Current cluster members:
192.168.1.102:5701 (hostname: alfnode2.localdomain)
192.168.1.101:5701 (hostname: alfnode1.localdomain)
También se puede ver que el cluster está bien configurado mediante la nueva consola de administración cuya URL es:
http://:8080/alfresco/service/enterprise/admin
En “Servicio de repositorio” y dentro de este en “Agrupación de servidores del repositorio” se puede ver toda la información del cluster, además se puede validar con el botón “Validar grupo” que realiza las comprobaciones necesarias para saber si ambos nodos se están comunicando correctamente:
Propiedades de Hazelcast
Todas las propiedades admitidas por Hazelcast en alfresco-global.properties son:
alfresco.cluster.enabled
Ejemplo: true
Descripción: Activa el cluster de Alfresco para este nodo
alfresco.cluster.interface
Ejemplo: 192.168.80.1
Descripción: Especifica la tarjeta de red usada para el cluster. Se puede usar tipo de dirección wildcard, por ejemplo 192.168.80.*
alfresco.cluster.nodetype
Ejemplo: NodoDesconectado001
Descripción: Especifica un nombre “amigable” para ese nodo del cluster, generalmente utilizado para servidores que se han unido al repositorio pero no forman parte del cluster (p.e. servidores de indexación)
alfresco.hazelcast.password
Ejemplo: mipasswd
Descripción: Define el password que usarán los nodos del cluster
alfresco.hazelcast.port
Ejemplo: 5701
Descripción: Establece el puerto de comunicación entre nodos del cluster
alfresco.hazelcast.autoinc.port
Ejemplo: false
Descripción: Realiza varios intentos de puertos para hayar uno libre desde la configuración alfresco.hazelcast.port. Alfresco no recomienda establecer esta propiedad
alfresco.hazelcast.mancenter.enabled
Ejemplo: false
Descripción: Activa las estadísticas y otros valores del cluster donde se puede acceder a través del Centro de gestión de Hazelcast
alfresco.hazelcast.mancenter.url
Ejemplo: http://localhost:8080/mancenter
Descripción: URL de acceso al centro de gestión de Hazelcast, evidentemente alfresco.hazelcast.mancenter.enabled debe estar en valor true
alfresco.hazelcast.max.no.heartbeat.seconds
Ejemplo: 15
Descripción: Tiempo máximo de monitorización para que se de por hecho que un nodo no está respondiendo
Configuración de Hazelcast en Share
En un entorno de cluster, Alfresco Share ahora utiliza Hazelcast para proporcionar mensajes entre los nodos de la capa web. Como resultado, las cachés ya no necesitan estar deshabilitadas para cualquier nodo. Cada uno funciona prácticamente tan rápido como una sola instancia de Share, mejorando así su rendimiento general.
Se pueden realizar dos configuraciones según las necesidades, con multicast o a nivel de TCP directo.
En todo caso, en balanceadores hay que seguir usando el sistema de Sticky-Session para funcionar correctamente. Hay que configurar correctamente el fichero share-config-custom.xml dentro de {extensionRoot}/alfresco/classes/web-extension poniendo correctamente el host y puerto de acceso al repositorio en caso necesario.
También hay que tener en cuenta que si se usa autenticación Kerberos o NTML con SSO las sesiones utilizarán la cookie JSESSIONID por lo que habrá que tenerla en cuenta por parte del balanceador.
Para esto hay que configurar el fichero custom-slingshot-application-context.xml
que hay en {extensionRoot}/alfresco/classes/web-extension (quitándole la extensión .sample)
Ejemplo para multicast:
<!– Hazelcast distributed messaging configuration – Share web-tier cluster
config (3.4.8 and 4.0.1) – see http://www.hazelcast.com/docs.jsp – and specifically
http://www.hazelcast.com/docs/1.9.4/manual/single_html/#SpringIntegration –>
<!– Configure cluster to use either Multicast or direct TCP-IP messaging
– multicast is default –>
<!– Optionally specify network interfaces – server machines likely to have
more than one interface –>
<!– The messaging topic – the "name" is also used by the persister config
below –>
<hz:topic id="topic" instance-ref="webframework.cluster.slingshot"
name=”slingshot-topic” />
<hz:multicast enabled="true" multicast-group="224.2.2.5"
multicast-port=”54327″ />
192.168.1.*
<bean id="webframework.slingshot.persister.remote"
class=”org.alfresco.web.site.ClusterAwarePathStoreObjectPersister”
parent=”webframework.sitedata.persister.abstract”>
alfresco/site-data/${objectTypeIds}
slingshot-topic
<bean id="webframework.factory.requestcontext.servlet" class="org.alfresco.web.site.ClusterAwareRequestContextFactory"
parent=”webframework.factory.base”>
Ejemplo para conexión directa TCP:
<!– Hazelcast distributed messaging configuration – Share web-tier cluster
config (3.4.8 and 4.0.1) – see http://www.hazelcast.com/docs.jsp – and specifically
http://www.hazelcast.com/docs/1.9.4/manual/single_html/#SpringIntegration –>
<!– Configure cluster to use either Multicast or direct TCP-IP messaging
– multicast is default –>
<!– Optionally specify network interfaces – server machines likely to have
more than one interface –>
<!– The messaging topic – the "name" is also used by the persister config
below –>
<hz:topic id="topic" instance-ref="webframework.cluster.slingshot"
name=”slingshot-topic” />
<hz:multicast enabled="false" multicast-group="224.2.2.5"
multicast-port=”54327″ />
alfnode1,alfnode2
192.168.1.*
<bean id="webframework.slingshot.persister.remote"
class=”org.alfresco.web.site.ClusterAwarePathStoreObjectPersister”
parent=”webframework.sitedata.persister.abstract”>
alfresco/site-data/${objectTypeIds}
slingshot-topic
<bean id="webframework.factory.requestcontext.servlet" class="org.alfresco.web.site.ClusterAwareRequestContextFactory"
parent=”webframework.factory.base”>
Centro de gestión Hazelcast (mancenter):
El centro de gestión Hazelcast (mancenter) permite monitorizar y administrar los servidores que ejecutan Hazelcast. Además, mancenter permite supervisar el estado general de los clústeres, y analizar y examinar las estructuras de datos en detalle.
Para instalarlo, se puede instalar tanto en un tomcat distinto como en el mismo de Alfresco. Solo hay que bajar una versión de Hazelcast (mancenter) y copiar el fichero mancenter-x.x.x.war al directorio de aplicaciones de tomcat.
Por ejemplo:
cp mancenter-2.4.1.war /opt/Alfresco422/tomcat/webapps/mancenter.war
Establecer la propiedad hazelcast.mancenter.home con el directorio donde se almacenan los datos, aquí se puede poner en la misma línea de opciones de Java (JAVA_OPTS), por ejemplo:
-Dhazelcast.mancenter.home=/opt/Alfresco422/tomcat/mancenter_data
Acordarse de activarlo en alfresco-global.properties:
alfresco.hazelcast.mancenter.enabled=true
Establecer la url de acceso, por ejemplo:
alfresco.hazelcast.mancenter.url=http://192.168.1.101:8080/mancenter
Por último, si se produce un error de serialización en el arranque, descomentar la siguiente línea en el contex.xml del servidor Tomcat:
Monitorización del funcionamiento de Hazelcast en Alfresco
La mejor forma como siempre es usando Log4j y para esto se puede usar la siguiente propiedad:
log4j.logger.org.alfresco.enterprise.repo.cluster=info
Para monitorizar la caché también se usan las siguientes propiedades:
log4j.logger.org.alfresco.enterprise.repo.cluster.cache=DEBUG
log4j.logger.org.alfresco.repo.cache=DEBUG
A nivel del propio Hazelcast:
log4j.logger.com.hazelcast=info
Y para aumentar el registro de seguimiento también se puede usar:
log4j.logger.com.hazelcast.impl.TcpIpJoiner=debug
Para finalizar
Las pruebas realizadas con un cluster de Alfresco One 4.2.2 usando Hazelcast han resultado ser muy satisfactorias, he realizado pruebas de subida de documentos, cambios de propiedades, etc. y eran instantáneas en ambos nodos.
Hay que tener en cuenta además que hay que configurar Solr (si se usa esta opción de indexado) correctamente para que se use de forma compartida, siempre y cuando no se utilize protocolo NFS para estos recursos compartidos de red ya que no está aconsejado. En este cado (uso de NFS) también se puede seguir usando una configuración similar a la que se utilizaba con Lucene, es decir, mantener índices locales por cada nodo.
Más información
http://docs.alfresco.com/4.2/concepts/ha-intro.html
http://hazelcast.org
http://unpocodejava.wordpress.com/2013/01/21/que-es-hazelcast/