Affinité de session avec WildFly et Apache


Lorsqu'on installe un cluster WildFly 8, l'accès Web aux différentes instances se fait via un intermédiaire qui est souvent Apache Web Server, avec un module dédié. Ce module peut être mod_jk, mod_proxy ou mod_cluster. A partir du moment où une application Web déployée dans le cluster utilise les sessions, elle devient stateful. Dans ce cas, il est conseillé de mettre en place l'affinité de session.

L'affinité de session est le mécanisme qui consiste à faire en sorte que si une session a été démarrée sur une instance pour un utilisateur, cet utilisateur sera toujours renvoyé vers la même instance. Pour mettre en place cette affinité, il faut généralement configurer WildFly et le module Apache.

Dans les exemples ci-dessous, on déploiera une application swmsg.war sur deux instances sur la même machines. Apache Web Server sera aussi sur la même machine.

WildFly + mod_proxy

Les instances de WildFly peuvent être démarrées dans un n'importe quel profil, HA ou pas. Ensuite, il faut préciser le node name de l'instance. Par défaut, c'est le hostname.

bin/standalone.sh -Djboss.node.name=instance1

Pour le second serveur, il faut en plus faire un décalage de ports pour éviter les conflits.

bin/standalone.sh -Djboss.node.name=instance2 -Djboss.socket.binding.port-offset=100

Théoriquement, l'application qu'on déploie doit être compatible avec le clustering. Pour cela, il faut que dans le fichier WEB-INF/web.xml, il y ait l'élément <distributable/>.

<?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"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">
   <distributable/>
   ...
</web-app>

J'ai dit théoriquement car j'ai constaté que le suffixe était ajouté même sans que l'application n'est pas déclarée <distributable/>.

Enfin, on configure mod_proxy de Apache. Le fichier exact dans lequel on configure ce module dépend fortement de la distribution et de l'installation de Apache Web Server. Pour savoir dans quel fichier et / ou répertoire travailler, relisez la documentation de votre installation. Dans tous les cas, ce fichier de configuration devra contenir la portion de configuration suivante :

<Proxy balancer://mycluster>
  BalancerMember http://localhost:8080 route=instance1      
  BalancerMember http://localhost:8180 route=instance2
</Proxy> 
<Location /swmsg>
  ProxyPass balancer://mycluster/swmsg stickysession=JSESSIONID  
</Location>

Avec cette configuration, chaque WildFly ajoutera son node name en suffixe du cookie de session et quand mod_proxy verra passer un cookie finissant par instance1, il le renverra vers le premier membre.

PS : avec JBoss AS 7, cette configuration fonctionne aussi, ainsi que la propriété -DjvmRoute qui a disparu en WildFly 8.

WildFly + mod_proxy (alternative)

Cette solution a l'avantage sur la première de pouvoir être utilisée pour un reverse proxy avec n'importe quelle cible, WildFly, Glassfish, ou des cibles non-java. Elle peut même être utilisée dans un environnement hétérogène. Cette solution générique utilise un cookie de route indépendant de celui de session, dans le mod_proxy.

Dans cet exemple, on crée un cookie ROUTEID qui est utilisé pour

Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/" env=BALANCER_ROUTE_CHANGED 
<Proxy balancer://mycluster>
  BalancerMember http://localhost:8080 route=alexis1
  BalancerMember http://localhost:8180 route=alexis2
</Proxy>
<Location /swmsg-web>
  ProxyPass balancer://mycluster/swmsg-web stickysession=ROUTEID
</Location>

Il n'y a rien à faire du coté de WildFly.

WildFly + mod_cluster

TODO

WildFly + mod_jk

Le load balancer du mod_jk est en affinité de session, par défaut. Il n'y a donc pas grand chose à faire... à part ouvrir le port AJP dans WildFly et configurer le worker lb dans mod_jk.

Commençons par WildFly. Dans la configuration initiale, le port AJP n'est pas ouvert. Il faut donc ajouter le listener AJP à Undertow. On peut par exemple utiliser jboss-cli :

/subsystem=undertow/server=default-server/ajp-listener=default-ajp:add(socket-binding=ajp)

A faire pour chaque instance WildFly. En utilisant un outil comme netstat, on constate que le port 8009 est ouvert (au décalage de port près).

Du coté de Apache Web Server, on doit installer le module mod_jk et configurer le load balancer. Même si on n'a rien configuré pour l'affinité de session, elle est activée par défaut.