L’installation de Tomcat en cluster est théoriquement simple et sobrement expliqué sur le site de Tomcat.
Pour résumer, il faut ajouter un élément <Cluster> dans le <Engine> ou le <Host> :
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
Simple, non ? Malheureusement, cela ne fonctionne pas toujours. N’est-ce pas Kilicool ? J’ai rencontré deux cas où il a fallu affiner cette configuration : un cluster avec deux instances de Tomcat sur la même machine, Windows ou Linux, et un cluster sous Linux. Cet article a été réalisé et testé avec Tomcat 6.
Configuration par défaut
En déclarant le cluster avec cette simple ligne, il faut être conscient qu’on met en place plusieurs éléments dans leur configuration par défaut.
Cette architecture du composant cluster se retrouve lorsqu’on utilise une configuration détaillée du Cluster.
Channel
Les éléments les plus délicats à configurer sont ceux du Channel. Ce sont eux qui assurent les communications entre les instances du cluster.
-
Membership communique en multicast pour découvrir d’autres membres sur la même adresse et le même port de multicast (228.0.0.4:45564, par défaut). Chaque instance envoie à cette adresse, sa propre adresse IP et le port sur lequel écoute le Receiver.
-
Receiver écoute sur un port (4000, par défaut) et réceptionne les changements d’états envoyés par les autres instances.
-
Sender envoie les changements d’état qui ont été réalisés sur sa propre instance. Il envoie ces changements à toutes les membres qui ont été découverts.
Manager
Le manager est le gestionnaire de session. Il remplace le Manager par défaut, en ajoutant des capacités de réplication. Bien que moins compliqué que le Channel, celui-ci nous a posé quelques soucis.
En effet, nous avions désactivé la persistance des sessions en activant la ligne du Manager dans le fichier conf/context.xml de Tomcat.
<Context>
<Manager pathname="" />
</Context>
Le problème, c’est que ce fichier est chargé après conf/server.xml, il écrase donc la définition du manager faite dans le Cluster. On s’est donc retrouvés avec des instances qui se trouvent, mais des applications qui n’échangent rien. Il ne faut donc pas activer cette ligne de configuration.
Cluster mono-machine
Gestion des ports
Tout d’abord, pour démarrer deux instances de Tomcat sur une même machine, il faut résoudre les conflits de ports. En plus des ports classiques (HTTP 8080, AJP 8009, SHUTDOWN 8005,…), il faut gérer le port du Receiver. Au passage, on va éviter des problèmes ultérieurs en branchant explicitement le Receiver sur l’adresse localhost.
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="localhost" port="4100"
autoBind="100" selectorTimeout="5000" maxThreads="6"/>
Ceci permet de démarrer les instances de Tomcat sur la même machine, mais ne leur permet pas de communiquer entre elles. Je n’ai pas d’explication certain, mais je pense que le dysfonctionnement vient du fait qu’un paquet multicast envoyé envoyés depuis une adresse IP n’est pas renvoyé vers la même adresse. Pour faire fonctionner ce cluster, il faut donc basculer vers une définition statique des membres du cluster, ou plutôt, ajouter une définition statique car la découverte dynamique reste active.
StaticMembership
Pour déclarer statiquement des membres, il faut ajouter un intercepteur de type StaticMembershipInterceptor dans lequel on peut ajouter un ou plusieurs membres.
<Interceptor className="org.apache.catalina.tribes.group.interceptors.StaticMembershipInterceptor">
<Member className="org.apache.catalina.tribes.membership.StaticMember"
host="localhost" port="4200"
securePort="-1" domain="local-domain"
uniqueId="{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}"/>
</Interceptor>
On reporte, et adapte cette configuration sur chaque instance du cluster. Résultat : les sessions des applications clusterisées sont répliquée.
Cluster Linux
L’objectif étant assez rarement de monter un cluster mono-machine, on peut estimer que cette recette est très peu utile. En fait, elle est utile dès qu’on veut déployer un cluster dans un environnement qui ne supporte pas le multicast. C’est généralement le cas dans des environnements WAN, car les routeurs internet ne laissent pas passer ce type de trafic. C’est le cas, aussi, sur certains systèmes, qui n’activent pas forcément le multicast par défaut.
Dans ce cas, deux solutions nous sont offertes : passer en membership statique ou activer le multicast.
Toutes ces questions nous avons dû nous les poser en déployer Tomcat en cluster en environnement Linux.
Linux et multicast
En fouinant sur les forums, on s’est posé cette première question : est-ce que nos connexions réseau sont compatibles avec le multicast ? Pour y répondre, un petit ifconfig nous informe :
$ ifconfig eth1
eth1 Link encap:Ethernet HWaddr 08:00:27:e6:28:d4
inet adr:192.168.56.52 Bcast:192.168.56.255 Masque:255.255.255.0
adr inet6: fe80::a00:27ff:fee6:28d4/64 Scope:Lien
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
...
Cette dernière ligne nous indique que, pour eth1, c’est OK.
Ensuite, est-ce que les paquets multicast sont envoyés au bon endroit, par la bonne interface réseau. Pour cela, on peut utiliser la commande route.
$ route
Destination Passerelle Genmask Indic Metric Ref Use Iface
10.0.2.0 * 255.255.255.0 U 0 0 0 eth0
192.168.56.0 * 255.255.255.0 U 0 0 0 eth1
default 10.0.2.2 0.0.0.0 UG 0 0 0 eth0
On constate qu’il n’y a pas de route spécifiée pour les adresses de multicast, et que la route par défaut passe par eth0 et non par eth1. Il est probablement possible d’ajouter une route pour le multicast (route add 228.0.0.4 eth1), mais on peut se débrouiller sans. Il faut surtout demander au receveur d’écouter sur la bonne adresse IP, et désactiver l’adresse automatique :
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
address="192.168.56.52" port="4200"
autoBind="100" selectorTimeout="5000" maxThreads="6"/>
Cette solution a fonctionné dans le cluster avec deux machines virtuelles Debian 5, sous VirtualBox. Elle a aussi fonctionné dans l’environnement VMWare avec du Suse 11 de Kilicool. Par contre, je ne pourrais pas garantir son fonctionnement dans tous les environnements, la diversité des solutions apportées dans les forums en temoigne.