I. Rolling Upgrade

Le Rolling Upgrade GlassFish est une technologie permettant de déployer une nouvelle application, de façon transparente pour l'utilisateur, tout en conservant sa session utilisateur.

Autrement dit, si un utilisateur est authentifié par exemple sur le frontoffice de la boutique et qu'il passe une commande, le déploiement d'une nouvelle version conserve son authentification et ses articles présents dans le panier. Ainsi, les mises à jour des applications ne nécessitent pas de redémarrage du serveur et surtout de coupure des services.

Comme expliqué précédemment, GlassFish supporte le versioning, permettant à l'administrateur de déployer de multiples versions d'une même application courante. Une seule application peut être activée à la fois. Le versioning et le cluster GlassFish facilitent le Rolling Upgrade. En effet, l'administrateur peut déployer une nouvelle version de l'application sans l'activer immédiatement par défaut en utilisant le paramètre --enabled=false. Ensuite, lorsque le déploiement est confirmé, il suffit à l'administrateur d'activer la nouvelle version de façon simple et rapide sans interrompre le fonctionnement du site (asadmin enable nouvelleversion).

Couplée au clustering expliqué précédemment, cette technique est encore plus pointue. En effet, le déploiement dynamique est automatiquement répliqué (dans un état désactivé) sur les instances du cluster ou grappe de serveurs. Les instances se synchronisent alors avec le DAS lorsque l'administrateur déploie une nouvelle application. Lorsque le déploiement est terminé, chaque instance active possède la précédente version de l'application et les fichiers pour la nouvelle version.

Ainsi, pour gérer le Rolling Upgrade avec un cluster et le versioning GlassFish, nous pouvons utiliser les étapes suivantes :

  • Désactiver l'instance courante (ex : in1) et envoyer le trafic Web de l'application sur une autre machine ou instance (ex : in2).
  • Déployer la nouvelle version de l'application en utilisant le versioning, afin d'activer automatiquement la nouvelle version et de désactiver l'ancienne : asadmin deploy --name=webcoleversioning:1 webcoleversioning_1.war.
  • Restaurer le trafic réseau sur la machine principale du cluster (in1).

Cette méthode ne nécessite pas de redémarrage du serveur du fait que GlassFish est capable de déployer une nouvelle version (dans un état désactivé) sans perturber le fonctionnement de la précédente version. L'administrateur n'a pas besoin de redémarrer chaque instance pour bénéficier des nouvelles versions.

Dans un environnement de production, nous avons parfois besoin d'arrêter une instance du serveur pour la maintenance ou le déploiement d'une nouvelle application, mais nous souhaitons couper l'instance proprement dès que toutes les requêtes existantes sont terminées.

Ce mécanisme appelé quiescing est supporté par le load balancer.

La mise en place du Rolling Upgrade nécessite les étapes suivantes :

  • Mise en place de l'architecture associée avec load balancing et/ou cluster.
  • Désactivation du trafic vers l'instance mise à jour.
  • Utilisation de la commande deploy et des paramètres --enabled et --target afin d'activer l'application en précisant la cible concernée.
  • Restauration du trafic à l'aide du load balancing vers l'instance concernée.

L'utilisation du couplage cluster/versioning permet de mettre en oeuvre le Rolling Upgrade.

La commande ci-dessous permet de déployer la version 1 de l'application webcoleversioning sur le cluster c1 :

 
Sélectionnez
asadmin deploy –-enabled=false –target= c1 webcoleversioning_1

La commande désactive l'application sur chaque instance déployée et active la nouvelle version.

Cette technique très proche de l'utilisation du load balancing permet une réplication automatique des applications ainsi que leur configuration sur tous les noeuds du cluster.

II. Répartition de la charge ou Load Balancing

Les concepts étudiés précédemment (clustering, versioning et Rolling Upgrade) peuvent être couplés au serveur Web Apache par l'intermédiaire du module mod_jk afin de répartir la charge entre plusieurs serveurs Java EE.

En effet, comme nous l'avons détaillé dans un paragraphe précédent, il est possible de coupler le serveur Web Apache avec le serveur Java EE GlassFish. Cette technique permet de gérer le cache des éléments statiques des applications Internet de façon optimisée (images, css, pages html...), mais également le load balancing.

Pour un cluster de plusieurs instances serveurs, l'utilisation du load balancing en frontal permet de simplifier l'accès aux applications, mais propose également un mécanisme de répartition de la charge. Le mécanisme de load balancing accepte les requêtes HTTP et HTTPS et les envoie à destination du serveur GlassFish adapté. Lorsqu'un serveur est défaillant, le load balancer peut détecter cette panne et distribuer le trafic réseau à destination d'une autre instance serveur. GlassFish peut fonctionner avec plusieurs outils de load balancing comme Apache, Sun Web Server ou encore Microsoft IIS. Enfin, GlassFish propose depuis sa version 3.1 un load-balancer.

Ainsi, grâce au module mod_jk, nous allons pouvoir configurer plusieurs workers ou nœuds du réseau, qui seront alors capables de traiter les requêtes/réponses. Pour mettre en oeuvre ce principe, nous allons utiliser le serveur Apache en frontal sur une machine du réseau ainsi que deux installations du serveur GlassFish. L'intérêt d'un tel dispositif, couplant toutes les techniques de gestion d'un serveur, est de mettre en oeuvre une architecture professionnelle capable de répartir la charge de façon optimisée en proposant de façon transparente de diviser le trafic réseau entre les différentes instances de GlassFish. Cette technique permet également de pouvoir détecter automatiquement si une machine du réseau est en panne, et d'envoyer le trafic sur une machine suivante, afin de proposer de la haute disponibilité. Enfin, elle permet de pouvoir déployer de nouvelles versions de l'application sans arrêter la mise en production du projet.

II-A. Mise en application d'une architecture professionnelle

L'architecture proposée dans le schéma ci-dessous correspond à un dispositif professionnel évolué. Bien entendu, dans l'idéal, chaque serveur doit être une machine différente (un serveur Apache, n serveurs GlassFish) afin de prévenir d'éventuelles pannes. Dans un premier temps nous utilisons une instance d'Apache avec le module mod_jk et le load balancing avec deux instances de GlassFish sur la même machine physique.

Image non disponible
Architecture load balancing sur machines séparées

La mise en oeuvre reprend les explications de la section Coupler GlassFish et le serveur Web Apache à l'aide du module mod_jk. Le module utilise le concept de worker. Un worker permet de gérer une instance précise de serveur Java EE. Chaque worker est identifié à partir d'un nom, d'un hôte et d'un port afin de gérer l'échange des messages, les workers étant définis dans le fichier worker.properties. D'après la directive JkWorkersFile du fichier de configuration Apache (apache2.conf), tout se passe dans le fichier de configuration des workers et du load balancing : /etc/apache2/workers.properties. Ce fichier contient désormais la configuration de deux workers ainsi que les directives adaptées au load balancing. Nous retrouvons nos deux instances de GlassFish, chacune étant associée à un worker (worker1 et worker2), et un worker nommé loadbalancer qui sera par la suite associé aux applications. Ce dernier worker est responsable de la répartition de la charge entre les autres workers.

Image non disponible
Mise en place du load balancing avec Apache et GlassFish

Le paramètre lbfactor de la configuration des workers est très important car il permet de préciser le facteur de charge d'un travailleur. Cette valeur précise le pourcentage de requêtes que l'instance GlassFish sera amenée à traiter. Dans notre cas nous utilisons 50, chaque serveur traitera la moitié des requêtes.

 
Sélectionnez
Code : /etc/apache2/workers.properties
# liste des workers
worker.list=worker1,worker2,loadbalancer
# -----------------------
# worker 1 - instance 1
# -----------------------
worker.worker1.port=8009
worker.worker1.host=192.168.0.5
worker.worker1.type=ajp13
worker.worker1.lbfactor=50
worker.worker1.cachesize=10
worker.worker1.cache_timeout=600
worker.worker1.socket_keepalive=1
worker.worker1.socket_timeout=3
# -----------------------
# worker 2 - instance 2
# ----------------------
worker.worker2.port=9009
worker.worker2.host=192.168.0.5
worker.worker2.type=ajp13
worker.worker2.lbfactor=50
worker.worker2.cachesize=10
worker.worker2.cache_timeout=600
worker.worker2.socket_keepalive=1
worker.worker2.socket_timeout=3
# -----------------------
# worker loadbalancer
# -----------------------
worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=worker1,worker2

La déclaration de l'hôte virtuel pour le domaine www.jwadg.com est identique au paragraphe étudié précédemment et permet de réaliser le routage à partir du nom de domaine.

 
Sélectionnez
Code : /etc/apache2/sites-available/jwadg
<VirtualHost *:80>
ServerName www.jwadg.com
ServerAlias jwadg.com
ServerAdmin info@gdawj.com
CustomLog /var/log/apache2/gdawj-access_log combined
<Location "/*">
JkMount loadbalancer
</Location>
</VirtualHost>

La configuration de l'hôte virtuel Apache, présente à cette adresse : /etc/apache2/sitesavailable/jwadg, est légèrement modifiée afin de préciser le worker loadbalancer à la place du worker1. Ainsi, l'application gdawj.war accessible à partir de ce domaine http://www.jwadg.com utilisera le worker loadbalancer qui s'occupera de la répartition de la charge entre les différentes instances.

Cette première ligne de commande lancée depuis la première installation de GlassFish (glassfishv3.1-in1) permet de créer un écouteur sur le port 8009 (listenerport) pour toutes les interfaces (listeneraddress) en correspondance avec l'hôte virtuel par défaut (server) et de le nommer jk-connector :

 
Sélectionnez
$ asadmin create-http-listener --listenerport 8009 --listeneraddress
0.0.0.0 --defaultvs server jk-connector

Cet écouteur HTTP est correctement configuré, nous devons maintenant activer le connecteur jk pour qu'il puisse dialoguer avec Apache en précisant son nom et l'activation du module (jk-enabled) :

 
Sélectionnez
$ asadmin set configs.config.server-config.network-config.networklisteners.
network-listener.jk-connector.jk-enabled=true

Il existe par défaut deux serveurs virtuels, server et __asadmin. Nous allons créer, par l'intermédiaire de l'interface en ligne de commande, un nouveau serveur virtuel pour notre domaine jwadg.com :

 
Sélectionnez
$ asadmin create-virtual-server --hosts www.jwadg.com,jwadg.com &#150;-
httplisteners jk-connector --defaultwebmodule gdawj jwadg

La ligne de commande ci-dessus permet de créer un hôte virtuel nommé jwadg pour les noms de domaine www.jwadg.com et jwadg.com avec, pour connecteur ou écouteur associé, jk-connector et comme application Java EE associée, gdawj. La configuration est terminée, il est nécessaire de redémarrer le serveur GlassFish pour activer le serveur virtuel et tester la configuration.

La dernière étape consiste à déployer l'application gdawj.war pour la première instance en précisant le serveur virtuel à utiliser lors du déploiement.

 
Sélectionnez
$ asadmin deploy &#150;virtualservers=jwadg gdwaj.war

Pour le moment, l'application est accessible à partir de l'URL http://www.jwadg.com/gdawj mais il est important d'afficher directement l'application sans saisir le nom du context-root. Pour cela, la dernière étape d'optimisation nécessite l'activation du module Web pour le serveur virtuel et un redémarrage du serveur. Ce paramètre est également accessible et configurable dans le fichier default-web.xml ;

 
Sélectionnez
$ asadmin set configs.config.server-config.http-service.virtualserver.
jwadg.default-web-module=gdawj

Les applications déployées sur les deux serveurs sont légèrement différentes (graphisme et texte) afin d'observer l'affichage depuis l'instance 1 ou l'instance 2.

Le fichier de configuration /glassfishv3.1-in2/glassfish/domains/domain1/config/domain.xml de la seconde instance de GlassFish (glassfishv3.1-in2) est légèrement modifié pour proposer d'autres ports à l'écoute afin de pouvoir démarrer deux instances depuis la même machine. La configuration utilise le port 9090 pour http-listener-1 (HTTP), 9191 pour http-listener-2 (HTTPS) et 24848 pour admin-listener (interface d'administration). Le reste de la configuration est identique à la précédente. Nous devons créer un connecteur jk à l'écoute du port 9009, activer le module jk et créer un serveur virtuel pour l'hôte www.jwadg.com, jwadg.com. Une seconde application gdawj.war est déployée sur la seconde instance afin de permettre une répartition de la charge.

Image non disponible
Affichage de l'application gdawj.war depuis l'instance 1

Maintenant, si nous simulons une panne en arrêtant la première instance de GlassFish (glassfishv3.1-in1), nous pouvons constater que la seconde instance (glassfishv3.1-in2) prend le relais et affiche l'application en proposant une haute disponibilité.

Image non disponible
Affichage de l'application gdawj.war depuis l'instance 2

Pour ce second exemple et cette nouvelle architecture, et afin d'améliorer le service, nous allons utiliser deux machines différentes pour les instances de GlassFish. La première machine d'adresse IP 192.168.0.4 contient l'installation d'Apache et de l'instance in1 de GlassFish. La seconde machine d'adresse IP 192.168.0.5 contient uniquement une seconde instance de GlassFish nommée in2. La configuration est identique à l'exemple précédent, seul le fichier /etc/apache2/worker.properties est modifié afin de préciser les deux serveurs concernés par le load balancing.

 
Sélectionnez
Code : /etc/apache2/workers.properties
# liste des workers
worker.list=worker1,worker2,loadbalancer
# -----------------------
# worker 1 - instance 1
# -----------------------
worker.worker1.port=8009
worker.worker1.host=192.168.0.5
...
# -----------------------
# worker 2 - instance 2
# ----------------------
worker.worker2.port=8009
worker.worker2.host=192.168.0.4
...
Image non disponible
Mise en place du load balancing sur plusieurs machines

D'après cette configuration, et si nous réalisons rapidement des actualisations des pages, nous pouvons constater que c'est de temps en temps le serveur in1 qui répond avec son application gdawj.war et d'autres fois le serveur in2. Ce procédé est tout à fait normal car nous avons configuré une répartition de la charge de type 50%/50%. Ainsi, suivant les accès, les serveurs répondront par intermittence.

Maintenant, si nous voulons gérer uniquement la tolérance de panne, c'est-à-dire utiliser l'instance in2 du serveur seulement si la première est en panne, nous devons rajouter les lignes suivantes dans le fichier de configuration du load balancing. La première ligne permet d'indiquer le worker failover et la seconde désactive la deuxième instance pour toutes les requêtes, excepté en cas de panne.

 
Sélectionnez
Code : /etc/apache2/workers.properties
...
# -----------------------
# worker loadbalancer
# -----------------------
worker.worker1.redirect=worker2
worker.worker2.disabled=true
worker.loadbalancer.type=lb
worker.loadbalancer.balanced_workers=worker1,worker2

II-B. Utiliser le load balancing, clustering et versioning

Il est enfin possible de coupler les technologies étudiées précédemment afin de bénéficier d'un système stable et souple. Nous pouvons en effet ajouter le concept de versioning. Pour cela, nous déployons une nouvelle version de l'application gdawj-versioning.war sur le second serveur :

 
Sélectionnez
$ asadmin deploy --virtualservers=jwadg --enabled=false --name=gdawj:beta-
V1.0 gdawj-versioning.war

Ensuite, nous pouvons changer la version de l'application sur la seconde machine et simuler une panne sur la première instance in1 :

 
Sélectionnez
$ asadmin enable gdawj:beta-V1.0
Image non disponible
Affichage d'une nouvelle version de l'application gdawj.war depuis l'instance 2

III. Embedded GlassFish

GlassFish peut être embarqué dans une JVM et donc ainsi être distribué avec une application totalement autonome. Ce principe de serveur embarqué (appelé embedded) peut par exemple être utilisé pour développer une application sur un petit serveur embarqué sur CD-ROM ou clé USB, sans avoir à déployer l'application sur un serveur installé en production.

En effet, GlassFish peut fonctionner en mode isolé sans nécessiter la totalité des classes dépendantes. Ainsi, nous pourrons alors télécharger une version embedded de GlassFish et juste la copier dans un répertoire de notre projet après déclaration dans le classpath. Cette API nommée embedded GlassFish peut être utilisée sans aucune autre librairie, à l'intérieur de la JVM client, en lieu et place du serveur GlassFish complet associé à sa propre JVM.

Dans le mode embarqué, une configuration minimum de GlassFish inclut les conteneurs appropriés et propose un environnement d'exécution léger. Le mode embarqué peut par exemple être utilisé facilement en phase de développement afin de proposer une version légère et facilement administrable.

Parmi les apports d'un tel concept nous pouvons citer :

  • Apporter de nouvelles fonctionnalités aux projets autonomes en bénéficiant de la technologie Java EE.
  • Utiliser le principe de Servlet, JSP ou encore EJB dans nos projets standalones.
  • Travailler en mode déconnecté et proposer le projet en local sur le poste client (sur disque dur, support USB ou autres) en utilisant la totalité du projet Web.
  • Tester la totalité de nos applications sans installer le serveur de production.
  • Créer NOTRE propre version du serveur en utilisant l'API Embedded avec ses librairies Jar et nos modules :
Image non disponible
Création de notre propre serveur GlassFish embarqué

Le serveur embarqué ne requiert pas d'installation ni de configuration, plusieurs fichiers et répertoires sont donc absents du système de fichier embarqué :

  • Le fichier default-web.xml.
  • Le fichier domain.xml.

L'utilisation de GlassFish en mode embarqué permet de réaliser les services suivants, mais pas la totalité des fonctionnalités du serveur :

  • Le support des technologies Web Java EE avec l'API Servlet, JavaServer Pages et JavaServer Faces.
  • La technologie JDBC ainsi que les pools, nécessitant la copie du pilote jdbc et la déclaration dans le classpath.
  • L'API JPA 1.0.