Clusteriser une application web avec TCServer et Terracotta
La majorité des applications produites de nos jours sont des applications web. Si leur conception et leur développement sont relativement bien maîtrisées, la mise en place de tests réalistes demeure trop souvent problématique en raison de la forte différence entre les environnements de développement et de production. En particulier, les problèmes de mise en cluster (load-balancing, réplication de session) et de montée en charge sont difficilement reproductibles localement.
Dans cet article, nous verrons comment utiliser TCServer et Terracotta pour mettre en place un mini-cluster de serveurs web en quelques minutes et déployer dessus une application simple avec réplication de sessions.
Notes préalables :
- Les répertoires et commandes présentés ici correspondent à un environnement Linux. Adaptez-les si besoin à votre propre environnement.
- L’étude de cas présentée ici utilise TCServer 6.0.19.A et Terracotta 3.0.1. Ces numéros de version peuvent apparaître dans des noms de répertoires ou de scripts. Adaptez-les au besoin.
- TCServer et Terracotta ont la fâcheuse tendance à être abrégés en “TC” et à utiliser des variables d’environnement reprenant cette notation, ce qui peut entraîner des petits problèmes de lisibilité…
Présentation de l’application web
Pour cet article, nous utiliserons une application web très simple, consistant à incrémenter un compteur de visites placé en session. L’unique page JSP affiche la valeur courante du compteur.
Afin de gérer proprement la concurrence d’accès au compteur de visites, l’application utilise une variable de type AtomicInteger, qui offre une méthode getAndIncrement() garantie atomique :
-
public class CounterServlet extends HttpServlet {
-
public static final String COUNTER_SESSION_ATTRIBUTE = “counter”;
-
public void doGet(HttpServletRequest request, HttpServletResponse response)
-
throws ServletException, IOException {
-
HttpSession session = request.getSession();
-
AtomicInteger counter = (AtomicInteger) session.getAttribute(COUNTER_SESSION_ATTRIBUTE);
-
int counterValue = counter.getAndIncrement();
-
request.setAttribute(“counterValue”, counterValue);
-
RequestDispatcher dispatcher = request.getRequestDispatcher(“/WEB-INF/jsp/counter.jsp”);
-
dispatcher.forward(request, response);
-
}
-
}
Un SessionListener permet d’initialiser un nouveau compteur à chaque création de session, et de garantir sa présence avant l’appel de la servlet :
-
public class CounterInitializerListener implements HttpSessionListener {
-
public void sessionCreated(HttpSessionEvent event) {
-
HttpSession session = event.getSession();
-
session.setAttribute(CounterServlet.COUNTER_SESSION_ATTRIBUTE, new AtomicInteger(0));
-
}
-
}
Le but est évidemment de constater que le compteur s’incrémente de manière continue lorsque l’application est correctement clusterisée.
Déploiement de TC Server
Installation de TC Server
Commençons par installer le cluster de serveurs web.
Sur le site de TCServer, téléchargez l’archive correspondant à votre système d’exploitation puis décompressez-la dans un répertoire temporaire. Lancez le script “run.sh
” et laissez-vous guider pour installer la SpringSource Application Management Suite (AMS) et/ou TCServer – pour cet article, nous nous contenterons de TCServer. Choisissez son répertoire d’installation, par exemple “/opt/Java/Tools/TCServer
” ; cet emplacement sera appelé “<TC_INSTALL_DIR>
” par la suite.
Pour éviter d’interférer avec une éventuelle installation préexistante de Tomcat sur votre machine, ajoutez la ligne suivante au début du script “<TC_INSTALL_DIR>/tcserver-ctl.sh
” :
export CATALINA_HOME=<TC_INSTALL_DIR>/tomcat-6.0.19.A
Attention à bien remplacer “<TC_INSTALL_DIR>
” par sa véritable valeur, et à adapter la version de Tomcat si nécessaire.
Création des instances
Nous allons maintenant créer deux instances de TCServer, qui formeront la base de notre mini cluster.
Ouvrez une console dans le répertoire “<TC_INSTALL_DIR>
“, puis invoquez le script “tcserver-instance.sh
” avec les paramètres suivants :
-v
: obligatoire, spécifie la version de TCServer. Adaptez-le en fonction de votre propre version.-s
: obligatoire, spécifie le nom de l’instance. Il est recommandé d’appliquer un pattern simple et cohérent.
Exemple :
-
tcserver-instance.sh -v 6.0.19.A -s instance1
-
tcserver-instance.sh -v 6.0.19.A -s instance2
Deux sous-répertoires “instance1
” et “instance2
” sont créés, contenant les éléments spécifiques aux instances (configuration, logs…). Le code binaire, commun, reste centralisé au niveau du répertoire “<TC_INSTALL_DIR>/tomcat-6.0.19.A/bin
“.
Configuration des instances
Il faut maintenant configurer les ports respectifs des instances (HTTP, JMX, etc.).
Sous Tomcat, cela nécessitait d’éditer le fichier “server.xml
“, ce qui pouvait se révéler fastidieux. TCServer étant prévu pour gérer de multiples instances quasi-identiques, leurs paramètres spécifiques sont astucieusement externalisés dans leurs fichiers “conf/catalina.properties
“.
Editez le fichier “conf/catalina.properties
” de chaque instance pour régler ses ports.
Là encore, l’application d’un pattern d’attribution est recommandé, afin de faciliter la gestion des serveurs. Par exemple :
Inst. 1 Inst. 2 ... Inst. N http.port 18081 18082 1808N jmx.port 18071 18072 1807N ajp.port 18061 18062 1806N
Déploiement et test de l’application
Déploiement
Il est temps de déployer l’application de démonstration.
Tout d’abord, copiez le fichier “WebCounter.war
” (disponible en pièce jointe de ce billet) dans le répertoire “webapps
” des deux instances, puis démarrez-les grâce au script “<TC_INSTALL_DIR>/tcserver-ctl.sh
” :
-
tcserver-ctl.sh instance1 start
-
tcserver-ctl.sh instance2 start
Vérifiez dans les logs que tout se passe bien.
Premier test de l’application
Testons maintenant notre installation.
Lancez votre navigateur web favori et accédez aux deux versions de l’application.
Si vous avez utilisé les réglages proposés ici, leurs adresses devraient être :
Rafraîchissez plusieurs fois la fenêtre de la première application : le compteur augmente, prouvant que la session HTTP utilisateur est active sur ce serveur.
Passez ensuite à la seconde application, et rafraîchissez-la également plusieurs fois. Le compteur repart de zéro puis est incrémenté, ce qui prouve que les sessions des deux versions de l’application sont indépendantes.
Nous allons maintenant activer la réplication automatique de session avec Terracotta, sans modifier l’application ni la configuration des instances.
Clusterisation avec Terracotta
Installation de Terracotta
Sur le site de Terracotta, téléchargez l’archive et décompressez-la dans un répertoire (par exemple “/opt/Java/Tools/Terracotta
“) que nous nommerons “<TERRACOTTA_INSTALL_DIR>
“.
Terracotta dispose de nombreux plugins facilitant la configuration des produits les plus courants, dont Tomcat. Leur gestion est confiée au script “<TERRACOTTA_INSTALL_DIR>/bin/tim-get.sh
“.
Tout d’abord, vérifiez la version courante du TIM Tomcat :
-
tim-get.sh list
Puis installez-le grâce à la commande :
-
tim-get.sh install tim-tomcat-6.0 1.1.0
Configuration des serveurs
Terracotta s’appuie sur un “Agent JVM” pour gérer la clusterisation des applications. Fonctionnant comme un plugin pour la JVM, il agit en instrumentant à la volée le code des classes, ce qui en fait une technologie totalement non-intrusive du point de vue applicatif.
L’agent Terracotta est activé en passant les options adéquates lors du démarrage des JVMs, grâce à la variable d’environnement “JAVA_OPTS
“.
Comme son ancêtre Tomcat, TCServer utilise le script “bin/setenv.sh
” pour positionner diverses variables d’environnement avant de se lancer. Nous allons éditer ce script afin d’inclure les variables propres à Terracotta.
Editez le fichier “bin/setenv.sh
” de chaque instance, et ajoutez-y les lignes suivantes :
export TC_INSTALL_DIR=<TERRACOTTA_INSTALL_DIR> export TC_CONFIG_PATH=$TC_INSTALL_DIR/tc-config.xml . $TC_INSTALL_DIR/bin/dso-env.sh -q export JAVA_OPTS="$JAVA_OPTS $TC_JAVA_OPTS"
Ne relancez pas les serveurs tout de suite : il nous faut d’abord configurer et lancer le serveur Terracotta.
Configuration de Terracotta
Terracotta lui-même est paramétré via le fichier de configuration dont l’emplacement est indiqué par la variable d’environnement TC_CONFIG_PATH paramétrée plus haut. Ce fichier est généralement nommé “tc-config.xml
” et placé à la racine du répertoire d’installation de Terracotta.
Il permet notamment de spécifier :
- Le port sur lequel le serveur Terracotta tournera
- Le répertoire contenant les données clusterisées
- Le répertoire les logs
- Les plugins spécifiques à activer (TIM ou Terracotta Integration Module)
- Les données à clusteriser, et en particulier les applications web dont les sessions devront être répliquées
Voici le fichier de configuration activant la mise en cluster des sessions de notre application :
-
<tc:tc-config xmlns:tc=“http://www.terracotta.org/config”
-
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
-
xsi:schemaLocation=“http://www.terracotta.org/schema/terracotta-4.xsd”>
-
<servers>
-
<server host=“localhost”>
-
<dso-port>9510</dso-port>
-
</server>
-
</servers>
-
<clients>
-
<modules>
-
<module name=“tim-tomcat-6.0” version=“1.1.0”/>
-
</modules>
-
</clients>
-
<application>
-
<dso>
-
<web-applications>
-
<web-application>WebCounter</web-application>
-
</web-applications>
-
</dso>
-
</application>
-
</tc:tc-config>
Notez l’activation du module Tomcat téléchargé précédemment, et la déclaration de l’application web de démonstration.
Lancement du serveur Terracotta
Pour finir, lancez le serveur Terracotta à l’aide du script “<TERRACOTTA_INSTALL_DIR>/bin/start-tc-server.sh
“.
Test de l’application clusterisée
Il est temps de tester à nouveau le comportement de notre application.
Relancez les deux instances de TCServer, et exécutez les même tests que précédemment.
Si tout s’est bien déroulé, le compteur est maintenant incrémenté de manière continue quel que soit le serveur utilisé, prouvant que les sessions HTTP sont bien répliquées entre les serveurs.
Conclusion
Si l’on excepte la phase d’installation des produits, nous constatons qu’il est très simple de mettre en place un mini-cluster web sur une machine de développement, et d’y déployer une application web aux sessions clusterisées.
Zenika est partenaire de SpringSource et de Terracotta, et fournit des services autour de ces technologies.