Url Link

Mise en oeuvre d'un site JCMS à haute disponibilité avec le protocole de réplication JSync

In brief...
Cet article décrit l'architecture, l'installation et la configuration d'un site JCMS à haute disponibilité en utilisant JSync, le protocole de réplication de JCMS. L'architecture proposée se compose d'un groupe de serveurs Tomcat 4 placés en aval d'un serveur Apache 2 configuré en répartition de charge au moyen du mod_jk.
Subject Architecture
Installation & Configuration
Products JCMS 5.0
JCMS 5.5
JCMS 5.6
JCMS 5.7
Published 3/18/08
Writer Olivier Dedieu

1. JCMS et la répartition de charge

La répartition de charge est une solution technique permettant d'assurer la haute disponibilité d'un site Web en distribuant les requêtes reçues sur plusieurs serveurs. Ce type d'architecture offre de nombreux avantages :

  1. Passage à l'échelle : pour améliorer les performances globale du système, il suffit d'ajouter de nouveaux serveurs.
  2. Tolérance aux pannes : si l'un des serveurs tombe, le répartiteur ne le sollicite plus et redistribue la charge sur les serveurs disponibles ;
  3. Flexibilité : Il est possible d'ajouter ou de retirer des serveurs à tout moment et l'effet est immédiat.

Depuis la version 4.1.0, JCMS intègre JSync, un moteur de réplication des données et des fichiers. Celui permet, entre autre, de construire des architectures à haute disponibilité basées sur la répartition de charge. La tâche principale de JSync est de synchroniser les données d'un groupe de serveurs JCMS, aussi appelés réplicas. Ainsi, toute création, modification ou suppression de données (catégorie, membre, contenu, …) sur l'un des réplicas sera propagée par le réplica leader aux réplicas membres du groupe. JSync assure ainsi la cohérence globale des données d'un groupe de serveur JCMS.

Les publications JCMS peuvent être accompagnées de documents. Il est important que chaque réplica puisse accéder à ces documents. Pour cela, deux solutions sont envisageables :

  1. Les réplicas accèdent à un répertoire partagé contenant les fichiers uploadés.
  2. Les fichiers uploadés sont répliqués par JSync sur les différents réplicas.

Bien que la seconde solution assure une indépendance des réplicas, nous recommandons de mettre en place la première solution dans le cadre d'architectures à haute disponibilité. D'une part, il existe différentes solutions simples pour partager le contenu d'un répertoire (NFS, Samba, …) D'autre part, la centralisation des fichiers uploadés réduit la consommation de bande passante entre les réplicas, allège les procédures de sauvegarde et simplifie l'architecture globale si JCMS Universal est utilisé. Néanmoins, pour faciliter la mise en oeuvre de notre exemple la réplication des fichiers sera activée.

Avec JSync, chaque serveur JCMS est indépendant pour l'accès aux données. Seules les écritures nécessitent des propagations. Or dans le fonctionnement normal d'un site JCMS, les consultations données sont très nettement supérieures aux écritures. Cela signifie donc, que chaque réplica sera capable de traiter la grande majorité des requêtes sans qu'il ait à contacter le reste du groupe. Et dans le cas où le leader devient indisponible, le réplica acceptera les écritures et ne les diffusera que lorsqu'un leader sera à nouveau disponible. JSync permet donc de construire des architectures robuste, sans goulot d'étranglement et sans SPF (Single Point of Failure).

Enfin, il est important de noter que le répartiteur de charge doit préserver les sessions utilisateur. En effet, JCMS stocke des données dans la session de l'utilisateur (le contenu du caddy, le workspace courant, langue, …). Ces données sont locales au serveur qui gère cette session. Si le client est aiguillé sur un autre serveur, il redémarrera une nouvelle session et perdra donc ces données. Pour cela, les répartiteurs supportent généralement l'affinité de session (sticky session). Ce mécanisme assure qu'un client qui a démarré une session J2EE sur le serveur, continuera à être aiguillé par le répartiteur sur ce serveur. En alternative à l'affinité de session, certains serveurs d'applications (p. ex., Tomcat 5) proposent la réplication des sessions entre les serveurs afin que le client retrouve les données de sa session quelque soit le serveur sur lequel il est aiguillé.

2. Architecture

L'architecture haute disponibilité la plus simple se compose d'un répartiteur de chargeur et de deux réplicas, l'un jouant le rôle de leader. Dans notre exemple, pour des raisons de simplicité et de coût, nous utiliserons Apache 2 comme répartiteur de charge. Néanmoins, pour les sites nécessitant une très haute disponibilité, il est recommander d'utiliser un véritable répartiteur de charge et une topologie réseau redondante. Ce type d'architecture est décrit en détail dans l'ouvrage Server Load Balancing de Tony Bourke (O'Reilly).

jcb lbt4 archi

Dans le cadre d'une évaluation simplifiée de cette architecture, il est possible de déployer le répartiteur de charge et le serveur leader (voire les deux serveurs Tomcat) sur une même machine. Dans ce cas, faites attention à modifier les adresses IP utilisées dans les fichiers de paramétrage décrit ci-dessous.

Dans cet article nous utilisons le serveur d'applications Tomcat. L'article Mise en oeuvre d’un site JCMS à haute disponibilité avec BEA Weblogic décrit la même problématique dans l'environnement BEA WebLogic.

3. Installation et configuration

L'installation se déroule en trois étapes :

  1. Installation et configuration des deux serveurs Tomcat ;
  2. Installation de JCMS sur les deux serveurs Tomcat et paramétrage de JSync ;
  3. Installation d'Apache, du mod_jk et configuration de la répartition de charge.

3.1 Installation et configuration des serveurs Tomcat

Les deux serveurs Tomcat 4.1.30 sont installés dans les répertoires tomcat1/ et tomcat2/ des serveurs 1 (192.168.0.3) et 2 (192.168.0.4). Pour chacun d'entre eux, éditez les fichiers conf/server.xml et faites les modifications décrites ci-dessous.

3.1.1 Déclaration du connecteur Coyote HTTP/1.1

Ce connecteur est utilisé pour les échanges JSync. Il permet aussi d'accèder directement à l'un des réplica sans passer par le répartiteur. Configurez ce connecteur pour qu'il écoute sur le port 9001 pour Tomcat1 et sur le port 9002 pour Tomcat2.

<!-- Define a non-SSL Coyote HTTP/1.1 Connector on port 9001 -->
<CONNECTOR className="org.apache.coyote.tomcat4.CoyoteConnector"
port="9001" minProcessors="300" maxProcessors="300"
enableLookups="true" redirectPort="8443"
acceptCount="300" debug="0" connectionTimeout="20000"
useURIValidationHack="false" disableUploadTimeout="true" />

3.1.2 Déclaration du connecteur AJP 1.3

Ce connecteur est utilisé pour la communication entre Apache/mod_jk et un serveur Tomcat. Configurez ce connecteur pour qu'il écoute sur le port 11009 pour Tomcat1 et sur le port 12009 pour Tomcat2.

<!-- Define an AJP 1.3 Connector on port 11009 -->
<CONNECTOR className="org.apache.ajp.tomcat4.Ajp13Connector"
port="11009" minProcessors="300" maxProcessors="300"
acceptCount="300" debug="0"/>

3.2 Installation et configuration de JCMS

3.2.1 Installation

Installez une version de JCMS 4.1.1 sur chacun des serveurs Tomcat dans le répertoire webapps/jcms/ et démarrez les deux serveurs Tomcat (pour plus de détails sur cette installation, reportez-vous au Manuel d'installation et d'exploitation de JCMS.

3.2.2 Configuration de JSync sur Tomcat1 (le leader)

Accédez au JCMS de Tomcat1 (http://192.168.0.3:9001/jcms/) et identifiez-vous en administrateur. Dans l'éditeur de propriétés, ouvrez l'onglet Réplication et entrez la configuration suivante :

jcb lbt4 prop1

3.2.3 Configuration de JSync sur Tomcat2

Accédez au JCMS de Tomcat1 (http://192.168.0.4:9002/jcms) et identifiez vous en administrateur. Dans l'éditeur de propriétés, ouvrez l'onglet Réplication et entrez la configuration suivante :

jcb lbt4 prop2

3.2.4 Vérification

Pour vérifier le bon fonctionnement de JSync, arrêtez Tomcat1 et Tomcat2. Relancez Tomcat1, puis, une fois qu'il est prêt, relancez Tomcat2. A la fin de son démarrage, Tomcat2 envoye une requête JSync pour se déclarer à son leader (Tomcat1). Pour vérifier que les 2 réplicas sont bien connectés, consultez le Gestionnaire de réplication (Admin > Avancé) sur chacun des réplicas.

Sur Tomcat1, Tomcat2 (t2) doit apparaître dans la liste des réplicas connectés

jcb lbt4 jsync1

Sur Tomcat2, Tomcat1 (t1) doit apparaître comme leader de Tomcat1.

jcb lbt4 jsync2

3.2.5 Test de la synchronisation

Pour tester que JSync assure bien la synchronisation des données et des fichiers entre les deux réplicas t1 et t2, il suffit de déposer un Document sur l'un et sur l'autre et de vérifier qu'après synchronisation, les 2 Documents sont bien présents avec leur fichier sur les deux réplicas.

Pour cela, créez 2 fichiers textes doc1.txt et doc2.txt. Ouvrez deux navigateurs, l'un sur Tomcat1 (http://192.168.0.3:9001/jcms/) et l'autre sur Tomcat2 (http://192.168.0.4:9002/jcms/). Sur Tomcat1 (resp. Tomcat2) publiez un Document avec doc1.txt (resp. doc2.txt). Au bout de 5 secondes, rechargez la page Tous mes contenus sur les deux navigateurs et vérifiez que les deux Documents sont bien présents sur chacun de deux réplicas. Consultez les fichiers pour tester qu'ils ont bien été répliqués.

Si vous rencontrez un problème de connexion et que vous avez configuré un proxy de sortie, vérifiez que l'adresse IP du noeud à contacter est bien prise en compte par la clause d'exclusion (Sauf pour) de la configuration du proxy de sortie.

3.3 Installation et configuration d'Apache en répartiteur de charge

3.3.1 Téléchargements

Téléchargez Apache 2.0.50. Dans les environnements Unix, il est préférable de télécharger la version avec les sources. Sur Windows, vous pouvez télécharger la version pré-compilée.

Télécharger le mod_jk 1.2.6 permettant de faire fonctionner Apache en répartiteur de charge avec Tomcat 4.

3.3.2 Installation sous Windows

Exécuter apache_2.0.50-win32-x86-no_ssl.msi et suivez les instruction d'installation.
Copiez le fichier mod_jk.dll dans C:\Program Files\Apache Group\Apache2\modules\.

3.3.2 Compilation d'Apache sous Unix

$> tar fvxz apache_2.0.50.tar.gz
$> cd apache_2.0.50/
$> ./configure
$> make
$> make install

Dans ce qui suit, on supposera qu'Apache a été installé dans le répertoire /usr/local/apache/.

3.3.3 Compilation du mod_jk sous Unix

$> tar jakarta-tomcat-connectors-jk-1.2.6-src
$> cd jk/native/
$> ./configure -with-apxs=/usr/local/apache/bin/apxs
$> make
$> cp apache-2.0/mod_jk.so /usr/local/apache/modules/

3.3.4 Référencement des ressources statiques dans Apache

Il est judicieux de faire servir les ressources statiques (images, css, javascript, ...) par Apache. Pour cela, faites le montages du repertoire 192.168.0.3:/usr/local/tomcat1/webapps/jcms dans le répertoire /usr/local/apache/jcms_apache/.

3.3.4 Configuration d'Apache

Editez le fichier /usr/local/apache/httpd.conf

Modifier la valeur du port pour qu'Apache écoute sur le port 9000.

# Listen: Allows you to bind Apache to specific IP addresses and/or
# ports, instead of the default. See also the <VIRTUALHOST>
# directive.
#
# Change this to Listen on specific IP addresses as shown below to
# prevent Apache from glomming onto all bound IP addresses (0.0.0.0
#
#Listen 12.34.56.78:80
Listen 9000

A la fin du fichier, ajoutez les lignes suivantes :

# ===================================
# Tomcat/mod_jk configuration
# -----------------------------------
# Load mod_jk
LoadModule jk_module libexec/mod_jk.so
# -----------------------------------
# Configure mod_jk
JkWorkersFile conf/workers.properties
JkLogFile logs/mod_jk.log
JkLogLevel info
# -----------------------------------
# Define resources served by Tomcat
JkMount /*.jsp loadbalancer
JkMount /upload/* loadbalancer
JkMount /archives/* loadbalancer
# -----------------------------------
# All the other resources are served by Apache
Alias / jcms_apache/
DirectoryIndex index.jsp
# -----------------------------------
# Prevent access to WEB-INF directory
<LOCATION WEB-INF ?>
AllowOverride None
deny from all
</LOCATION>
<DIRECTORY WEB-INF ? usr local apache jcms_apache>
AllowOverride None
deny from all
</DIRECTORY>

3.3.5 Configuration de la répartition de charge (workers.properties)

Dans le répertoire /usr/local/apache/conf/, créez le fichier workers.properties. Ce fichier indique à Apache les serveurs Tomcat sur lesquels répartir de charge. Les valeurs des ports indiquées dans ce fichier sont celles définies dans le connecteur AJP 13 de la configuration des serveurs Tomcat (11009 et 12009). Pour plus de détails sur la configuration des workers, consultez la documentation du mod_jk.

# list the workers by name 
worker.list=tomcat1, tomcat2, loadbalancer
# ------------------------
# Tomcat 1
# ------------------------
worker.tomcat1.port=11009
worker.tomcat1.host=192.168.0.3
worker.tomcat1.type=ajp13
# Specifies the load balance factor when used with
# a load balancing worker.
# Note: lbfactor must be > 0.Low lbfactor means less work done by the worker.
worker.tomcat1.lbfactor=100
# ------------------------
# Tomcat 2
# ------------------------
worker.tomcat2.port=12009
worker.tomcat2.host=192.168.0.4
worker.tomcat2.type=ajp13
# Specifies the load balance factor when used with
# a load balancing worker.
# Note: lbfactor must be > 0. Low lbfactor means less work done by the worker.
worker.tomcat2.lbfactor=100
# ------------------------
# Load Balancer worker
# ------------------------
# The loadbalancer (type lb) worker performs weighted round-robin
# load balancing with sticky sessions.
# Note: if a worker dies, the load balancer will check its state
# once in a while. Until then all work is redirected to peer
# worker.
worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=tomcat1, tomcat2
worker.loadbalancer.sticky_session=1

Démarrez Apache et vérifiez qu'il fonctionne correctement en allant sur l'URL de la page d'accueil, http://192.168.0.2:9000/

4. Tests

4.1 Test de répartition

Pour vérifier que la répartition de charge fonctionne, ouvrez un navigateur sur deux machines ou deux navigateurs différents sur la même machine (p. ex. Mozilla et FireFox). Sur chaque navigateur, interrogez http://192.168.0.2:9000/jcms/status.jsp. Apache va diriger la première requête sur Tomcat1 puis la seconde sur Tomcat2. L'un doit donc afficher la page de statut de JCMS sous Tomcat1 et l'autre celle de JCMS sous Tomcat2. Avec chaque navigateur, consulter la page d'accueil de JCMS. Puis revenez sur la page de statut afin de vérifier que l'affinité de session est bien préservée.

Afin de vous permettre de savoir à tout moment quel réplica à répondu, dans l'espace de travail et dans l'espace d'administration, le nom du réplica est affiché en bas de la page.

jcb lbt4 footer

4.2 Test de tolérance aux pannes

Pour vérifier la tolérance aux pannes, arrêtez le serveur Tomcat2 et rechargez la page http://192.168.0.2:9000/jcms/status.jsp avec le navigateur qui était connecté à Tomcat2. Il devrait maintenant être automatiquement aiguillé sur Tomcat1.

Redémarrez Tomcat2. Arrêtez et relancez le navigateur précédemment utilisé. Accédez à la page http://192.168.0.2:9000/jcms/status.jsp. Il devrait maintenant à nouveau fonctionner avec Tomcat2.

5. Configurations avancées

5.1 Réduire les risques de conflits

Des conflits peuvent survenir durant les phases de divergence des réplicas. JSync résout automatiquement les conflits portant sur un même objet (p. ex. deux mises à jour concurrentes) mais ne résout pas les conflits inter-objets (p. ex. création d'une catégorie sous une catégorie mère et suppression de la catégorie mère). Une solution pour éviter de tels conflits consiste à centraliser les majorités des écritures sur le même réplica. Pour cela, il faut que les contributeurs du site utiliser l'URL d'accès direct à ce réplica (p. ex. : http://192.168.0.3:9001/jcms/ pour accéder à Tomcat1) et non l'adresse publique qui passe par le répartiteur de charge.

5.2 Répartition hétérogène et fail-over

Il est possible de pondérer la répartition de charge entre les réplicas. Ce paramétrage se fait en agissant sur l'attribut lbfactor dans le fichier workers.properties (cf. section 3.3.5). Lorsque le lbfactor est à la même valeur entre les réplicas, la distribution est homogène. Si le lbfactor est à 0 le réplica n'est jamais sollicité sauf si il est le seul à être disponible. Cette particularité permet de monter des architectures en fail-over : un réplica secondaire ne prend la main que lorsque le réplica principal est tombé.

5.3 JCMS JUniversal

Si JCMS Universal doit être utilisé, il est fortement recommandé d'opter pour une centralisation des fichiers uploadés. Dans ce cas, il faut mettre en place un répertoire upload partagé entre les réplicas et JCMS JUniversal et désactiver la réplication des fichiers (cf. section 3.2.2) sur tous les réplicas.

5.4 DeployManager

Il est possible d'utiliser le DeployManager pour déployer des nouveautés sur les réplicas. Pour cela, installez un DeployManager par serveur et suivez la procédure de déploiement décrite à la section 6.5.

5.5 Sécurité

JSync ouvre une porte d'accès à l'ensemble des données de la webapp en lecture et en écriture. Pour des raisons de sécurité élémentaire, il est important de limiter les machines pouvant faire des requêtes JSync aux différents réplicas. Le principe consiste à définir pour chaque réplica la liste des machines autorisées à dialoguer avec le réplica. Ce paramétrage se fait dans le champ Filtre Adresse IP des propriétés de la réplication en déclarant une expression régulière décrivant les adresses autorisées. Par exemple, l'expression régulière ^192.168.0.\d+$ limite l'accès aux machines du réseau local .

6. Procédures d'exploitation

6.1 Ajout d'un réplica

Pour faire face à une montée en charge, il faut pouvoir ajouter de nouveaux réplicas. Pour cela, il suffit de d'installer une copie de l'un des serveurs déjà opérationnel. Cette copie doit néanmoins être adaptée. Voici la procédure pour ajouter un serveur Tomcat3 dans notre architecture :

  1. Copier en totalité le répertoire tomcat2/ en tomcat3/ ;
  2. Editer tomcat3/conf/server.xml et modifier les port d'écoute HTTP (p.ex 9003) et AJP (p. ex. 13009) dans server.xml ;
  3. Dans le fichier WEB-INF/data/custom.prop, mettre la propriété jsync.enable à false (afin qu'il ne contact pas le leader avec l'identité de Tomcat2)
  4. Démarrer Tomcat3 et faire le paramétrage JSync (cf. section 3.2.3)
  5. Redémarrer Tomcat3
  6. Déclarer Tomcat3 dans le fichier workers.properties (cf. section 3.3.5) et redémarrer Apache pour que cette nouvelle configuration soit prise en compte.

6.2 Retrait d'un réplica

Pour désactiver un réplica (c'est-à-dire, pour qu'il ne reçoive plus de charge du répartiteur), il suffit de mettre son lbfactor à 0 dans le fichier workers.properties (cf. section 3.3.5) et de redémarrer Apache pour que cette nouvelle configuration soit prise en compte.

6.3 Réintroduction du leader

Si le réplica leader Tomcat1 tombe, les réplicas membres (Tomcat2, Tomcat3, …) ne peuvent plus propager leurs écritures. Néanmoins, chaque réplica membre continuera d'essayer de propager ses nouvelles écritures au leader. Lorsque celui-ci sera à nouveau opérationnel, les réplicas membre pourront à nouveau le contacter mais se verront refuser la synchronisation car le leader ne les connaît pas (dans le journal, code de retour 403 - URID inconnu). Il faut donc procéder à la réintroduction de tous les réplicas membres au près du leader. Pour cela, sur chaque réplica membre, allez dans Gestion de la réplication et cliquez sur le bouton Déconnexion puis sur le bouton Contacter le leader.

A partir de JCMS 5.7.4, le leader peut être configuré pour que, lors de son démarrage, un message JSync soit envoyé forçant chaque réplica à se reconnecter. Pour activer cette fonctionnalité, il suffit de saisir une durée (p. ex. 5 secondes) dans la propriété Reconnexion des réplicas au démarrage.

Par défaut, la liste des réplicas à contacter est automatique alimentée d'après les précédentes connexions. Elle peut aussi être définie explicitement dans l'éditeur de propriétés.

jcms574-jsync

6.4 Manipulation du store

Si le store doit subir des modifications tel qu'un nettoyage, il convient de suivre rigoureusement la procédure suivante.

  1. Sur chaque réplica membre, désactiver les écritures sur tous les réplicas membres (Admin > Propriété > Site > Accès) et propager les dernières écritures au leader (Admin > Gestionnaire de répliation > Propager au leader) ;
  2. Retirer le leader (Tomcat1) de la répartition de charge ;
  3. Faire la manipulation du store sur le leader. Dans le cas d'un nettoyage du store ceci nécessite de désactiver JSync au préalable (Admin > Propriété > Réplication) ;
  4. Une fois la manipulation terminée, recopier le fichier store.xml du leader sur tous les réplicas membres.

6.5 Déploiement par le DeployManager

Le DeployManager peut non seulement modifier le store mais aussi les types, les JSP, les workflows, … Aussi, il faut suivre la procédure suivante pour le déploiement des nouveaux développements sur l'ensemble des réplicas. Cette procédure assure la continuité de service durant toute la phase de déploiement.

  1. Sur chaque réplica membre, désactiver les écritures (Admin > Propriété > Site > Accès) et propager les dernières écritures au leader (Admin > Gestionnaire de réplication > Propager au leader) ;
  2. Désactiver les écritures sur le leader ;
  3. Arrêter le leader ;
  4. Mettre à jour le leader avec le DeployManager ;
  5. Redémarrer le leader ;
  6. Pour chaque réplica membre ;
    1. Arrêter le réplica ;
    2. Mettre à jour le réplica avec le DeployManager ;
    3. Remplacer son store.xml par celui du leader ;
    4. Redémarrer le réplica.
  7. Réactiver les écritures sur les réplicas membres ;
  8. Réactiver les écritures sur le leader.

 


Member Discussions

    Title First post Last post Writer #Messages
1. réplication pré-production sur la production 7/7/08 11:14 AM 10/15/08 5:39 PM Benoît Moraillon 5
2. Duplication de site avec JSynch 12/15/06 2:46 PM 9/16/08 1:55 PM Christophe Danière 3
3. Jsync limitation de JVM 5/6/08 5:36 PM 5/6/08 5:36 PM Christophe GRIVA 1
4. Erreur possible dans l'exemple workers.properties 4/7/08 5:54 PM 4/7/08 6:03 PM Benjamin BARBIER 2

Login   Home   fr en
JALIOS SA - SIREN 440 126 035