Analyse, monitoring et supervision d'Apache Tomcat

Jérôme Lafosse

Cet article est un extrait gratuit de l'ouvrage Java EE - Guide de développement d'applications web en Java, Chapitre 2 : Le serveur d'applications Apache Tomcat, section "Analyse, monitoring et supervision".

Commentez

- Titre : Analyse, monitoring et supervision d'Apache Tomcat

- Auteur : Jérôme Lafosse

- Parution : 15 juillet 2009

- Mise à jour : 15 juillet 2009

- Licence : Copyright ® 2009 Jérôme Lafosse / ENI. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- 1. Présentation

- 2. Tester la montée en charge

- 3. JConsole et MC4J, des consoles JMX

- a. JConsole

- b. MC4J

- 4. JMeter et les tests de montée en charge

1 - Présentation

Le système de journalisation de Tomcat et de Java est très complexe et évolué. Tomcat utilise la bibliothèque Jakarta commons-logging. Cette bibliothèque fait partie du projet Jakarta de la fondation Apache. Le projet contient un ensemble de bibliothèques de développement Java très variées. La librairie commons-logging est semblable à la bibliothèque Log4J et permet la journalisation tout comme l'API java.util.logging de Java.

Le fichier de journalisation de Tomcat utilise le fichier de configuration /conf/logging.properties. C'est le principal fichier de configuration pour le serveur mais chaque application déployée peut fournir son propre fichier logging.properties dans son répertoire /WEB-INF/classes.

La machine virtuelle de Java est responsable de la réservation de l'espace mémoire nécessaire à l'application. Au démarrage de l'application, celle-ci réserve de la mémoire auprès du système d'exploitation. Si l'application nécessite plus de mémoire que cette valeur limite, alors la machine virtuelle s'arrête en déclenchant l'erreur java.lang.OutOfMemoryError. Cette erreur est très fréquente en Java et doit donc être évitée au maximum.

Il est donc extrêmement important de mesurer et surveiller la consommation mémoire du serveur dans la machine virtuelle pour anticiper ce problème. La configuration de la machine virtuelle peut être visualisée par le biais du manager à cette adresse : http://localhost:8080/manager/status.

On retrouve la quantité de mémoire disponible (Free Memory) dans la machine virtuelle, la mémoire utilisable (Total Memory) et la mémoire maximum allouable auprès du système (Max Memory).

2 - Tester la montée en charge

Nous réaliserons par la suite des tests de montée en charge avec l'outil JMeter. Il est également possible de visualiser le nombre de connexions JDBC disponibles à un instant précis, le nombre de threads occupés, la mémoire consommée, les classes chargées...

Java Management Extensions JMX est une API Java conçue pour la supervision des applications. JMX est intégrée à partir de la plateforme Java 1.5. Actuellement, JMX est le standard pour le développement des outils de supervision et d'administration dans les technologies Java.

Dans une machine virtuelle Java, il est possible d'associer aux différents objets Java des composants qui permettent d'obtenir des informations sur l'exécution et le traitement des objets. Ces composants sont appelés des MBeans. Ces MBeans sont accessibles via l'élément central, le serveur MBeans qui est capable d'utiliser des protocoles variés pour la connexion d'outils de supervision.

Donc les données des MBeans peuvent être accédées grâce à un client JMX en local ou bien à distance. Tomcat crée des MBeans dynamiquement pendant son exécution, lorsque des applications déployées fonctionnent sur le serveur. Les MBeans dynamiques de Tomcat sont créés grâce aux éléments de configuration appelés <Listener> présents dans le fichier server.xml.

Les informations JMX sont disponibles à partir du manager à l'URL http://localhost:8080/manager/jmxproxy/. Il est ainsi possible d'obtenir des informations sur les connecteurs, les threads, les classes...

Il est possible d'utiliser des filtres et par exemple d'afficher uniquement les informations sur les objets MBean de type ThreadPool http://localhost:8080/manager/jmxproxy/?qry=Catalina:type=ThreadPool,*.

3 - JConsole et MC4J, des consoles JMX

L'ergonomie offerte par le manager de Tomcat est limitée et il est assez difficile de comprendre les paramètres en temps réel. Il existe ainsi plusieurs outils évolués qui permettent d'afficher des rapports détaillés.

a - JConsole

Pour pouvoir obtenir des statistiques en temps réel, il faut utiliser un client lourd JMX. Le logiciel JConsole développé par Sun et livré en standard avec le JDK 1.6 permet d'utiliser JMX. Son utilisation est assez simple et permet la création de graphiques en temps réel. Si JConsole est lancé par défaut sans rien indiquer (/jdk/bin/jconsole), nous obtenons des informations sur la machine virtuelle Java installée sur le poste local. Les données ne sont pas "correctes" car elles ne concernent pas uniquement la machine virtuelle de Tomcat. Pour cela, il est nécessaire de configurer Tomcat avec un connecteur en lui passant des options au démarrage (port pour se connecter au serveur Mbean...). De même, il est important de sécuriser cette connexion par identifiant et mot de passe afin d'éviter à des hôtes distants de se connecter à notre machine.

Sous Windows

Avant de pouvoir connecter Tomcat à JConsole, il faut configurer la machine virtuelle Java du serveur pour autoriser l'accès distant de son connecteur. Pour cela, il est nécessaire d'ajouter des options à la machine virtuelle via le script de démarrage de Tomcat. Pour cela, il est nécessaire de configurer la sécurité d'accès au connecteur.

Sécurité

La configuration de la sécurité démarre par la création des fichiers jmxremote.access et jmxremote.password. Il existe plusieurs possibilités pour la mise en place de ces fichiers. Ces fichiers peuvent être utilisés dans le répertoire /conf du serveur Tomcat ou dans le répertoire /jdk/jre/lib/management de l'installation du JDK Java (c'est cette seconde option qui est utilisée dans ce guide).

Le fichier jmxremote.access permet d'indiquer les noms d'utilisateurs autorisés à utiliser le connecteur ainsi que les permissions sur le connecteur.

Le fichier jmxremote.password contient les mots de passe associés aux utilisateurs.

Le répertoire /jdk/jre/lib/management contient des fichiers d'exemples qui peuvent être renommés pour l'utilisateur.

Nous allons copier et renommer le fichier jmxremote.password.template en jmxremote.password. Nous ajoutons ensuite notre utilisateur en fin de fichier.

# Following are two commented-out entries. The "measureRole" role has
# password "QED". The "controlRole" role has password "R&D".
#
# monitorRole QED
# controlRole R&D
moniteurjava monmotdepasse

Nous pourrons donc utiliser cet utilisateur avec son mot de passe pour se connecter au serveur MBean mais pour le moment, nous ne pourrons rien faire car l'utilisateur ne possède aucun droit. Le fichier jmxremote.access permet de définir les droits en fonction des utilisateurs du fichier jmxremote.password.

Nous éditons donc ce fichier et ajoutons la ligne suivante :

# Default access control entries:
# o The "monitorRole" role has readonly access.
# o The "controlRole" role has readwrite access.
monitorRole readonly
controlRole readwrite
moniteurjava readwrite

L'option readwrite permet d'indiquer qu'il sera possible de réaliser des opérations de lecture sur les objets MBean mais aussi d'écriture ce qui est important par exemple pour vider à distance le garbage collector de la machine virtuelle. Il faut désormais démarrer la machine virtuelle de Tomcat avec un connecteur activé en passant des optionsau démarrage. Pour cela si le serveur Tomcat est installé avec une archive, le fichier /bin/catalina.bat peut être modifié.

Par contre, si le serveur Tomcat a été installé en mode service, c'est-à-dire avec l'installation pour Windows, ce fichier n'est pas présent. Il faut dans ce cas ajouter des paramètres dans la console Tomcat ou dans Eclipse pour le démarrage de Tomcat.

-Dcom.sun.management.jmxremote.port=8364
-Dcom.sun.management.jmxremote.authenticate=true
-Dcom.sun.management.jmxremote.password.file=
E:\jdk1.6\jre\lib\management\jmxremote.password
-Dcom.sun.management.jmxremote.access.file=
E:\jdk1.6\jre\lib\management\jmxremote.access
-Dcom.sun.management.jmxremote.ssl=false

Si le serveur est lancé, alors l'erreur suivante est obtenue dans la console d'Eclipse.

Cette erreur indique que le propriétaire du fichier doit être l'utilisateur qui démarre le serveur.

Sous Windows XP, dans le menu Outils, il faut choisir Options des dossiers, puis dans la fenêtre cliquer sur l'onglet Affichage et décocher Utiliser le partage de fichiers simple. Cette action permet de gérer la sécurité sur les fichiers.

Il faut ensuite réaliser un clic droit sur le fichier jmxremote.password puis sélectionner l'onglet Sécurité et cliquer sur le bouton Paramètres avancés. Il faut alors sélectionner l'onglet Autorisations et décocher la case Hérite de l'objet parent les entrées...

Une boîte de dialogue apparaît alors, il faut répondre Copier à la question posée.

Ensuite, dans la partie Autorisations, il faut supprimer tous les utilisateurs autorisés et sélectionner l'utilisateur Administrateur du système qui a les droits sur la machine virtuelle Java.

Nous ne devons nous retrouver qu'avec notre utilisateur autorisé.

Le serveur Tomcat peut être lancé, le message d'erreur disparaît. Désormais si nous lançons l'outil JConsole, nous pourrons toujours nous connecter en local mais également à la partie des objets MBean qui contrôlent Tomcat.

Pour cela, il faut utiliser nos informations de connexion.

Le champ Remote Process correspond à l'adresse locale de la machine et au port MBeans. Les champs Username et Password correspondent aux informations de connexion du fichier jmxremote.password.

Dans ce cas de figure, les indications sont correctes et conformes à celles indiquées par le manager de Tomcat. Des informations précises sur les applications déployées par le serveur sont obtenues. Dans le premier onglet, il y a un résumé pratique avec les Threads exécutés, la consommation de la mémoire et les classes chargées. Le deuxième onglet permet d'afficher des informations sur la consommation mémoire ce qui est indispensable lors de développement de gros projets afin de vérifier si les connexions JDBC ne sont pas fermées, si des classes ou Servlets consomment trop de mémoire... Les derniers onglets permettent d'avoir des informations sur les Threads, classes, objets MBean et la machine virtuelle.

Nous voyons ici un fonctionnement conforme de la mémoire avec les parties chargement et déchargement.

Sous Linux

Sous Linux l'installation est pratiquement identique. Nous éditons le fichier /usr/local/tomcat/bin/catalina.sh qui permet de démarrer Tomcat. Nous ajoutons alors uniquement les deux lignes suivantes en milieu de fichier vers la ligne 260 qui est relative à la variable JAVA_OPTS et qui correspond au démarrage.

-Dcom.sun.management.jmxremote.port=8364
-Dcom.sun.management.jmxremote.ssl=false

Nous procédons ensuite comme sous Windows et nous copions le fichier d'exemple jmxremote.password.template en jmxremote.password.

#cp /usr/local/jdk/jre/lib/management/jmxremote.password.template
/usr/local/jdk/jre/lib/management/jmxremote.password

Nous modifions les droits sur ce fichier.

#chmod 744 jmxremote.password

Comme sous Windows, nous ajoutons notre utilisateur JMX au fichier jmxremote.password.

# Following are two commented-out entries. The "measureRole" role has
# password "QED". The "controlRole" role has password "R&D".
#
# monitorRole QED
# controlRole R&D
moniteurjava monmotdepasse

Pour la gestion des droits sur le fichier, c'est plus simple que sous Windows, il suffit de positionner les droits suivants sur le fichier.

#chmod 600 jmxremote.password

Ensuite, ce qui est important c'est que l'utilisateur qui lance la JVM soit le propriétaire de ce fichier.

#chown tomcat:tomcat jmxremote.password

Désormais, nous allons déclarer nos droits avec le fichier jmxremote.access.

# o The "monitorRole" role has readonly access.
# o The "controlRole" role has readwrite access.
monitorRole readonly
controlRole readwrite
moniteurjava readwrite

L'application de supervision et le connecteur sont désormais opérationnels. Il est donc possible d'utiliser une interface distante pour se connecter au serveur et obtenir des informations de supervision.

b - MC4J

MC4J est une application JMX encore plus puissante que JConsole. Ce logiciel libre simple d'utilisation est téléchargeable à l'adresse suivante : http://mc4j.org.

Ce logiciel est orienté vers la supervision des serveurs d'applications Java EE. MC4J est par exemple compatible avec Tomcat, JBoss, Weblogic, WebSphere... Il est également disponible pour la majorité des systèmes d'exploitation avec une version pour Windows, Linux et Mac OS X. Après le téléchargement et l'installation du logiciel, il peut être lancé depuis la machine locale ou n'importe quelle machine distante capable d'accéder à la machine locale.

Après le démarrage de MC4J, il faut configurer une connexion au serveur Tomcat en choisissant Create Server Connection dans le menu Management de l'interface graphique. En premier, le type de serveur auquel se connecter doit être indiqué. Il faut ensuite donner un nom à notre connexion et le numéro de port pour la connexion. Ensuite, si la sécurité est activée sur le serveur d'applications, il faut saisir les informations d'authentification.

Lors de la deuxième étape, l'assistant demande de préciser le répertoire d'installation de Tomcat. Dans le cas où MC4J et le serveur Tomcat à superviser sont sur des machines différentes, il faudra tout de même installer une version de Tomcat en local (avec une version identique du serveur à superviser) car MC4J utilise les classes de Tomcat pour la supervision.

Une fois la connexion établie, l'écran principal de la console MC4J apparaît avec la liste des MBeans du serveur. Le temps de chargement peut parfois être assez long en fonction de la connexion réseau et de la taille du projet à superviser. Beaucoup d'informations utiles pour la supervision du projet sont alors affichées comme les classes chargées en mémoire, les connexions JDBC, les requêtes des clients.

Avec un outil comme MC4J, il est désormais assez facile de suivre l'évolution en temps réel des ressources internes du serveur pendant un test de montée en charge ou le développement de celuici. Cet outil est également très pratique sur un serveur en production, il fait partie des logiciels indispensables d'un administrateur de serveur Java EE.

4 - JMeter et les tests de montée en charge

Après avoir correctement configuré le serveur et les outils de supervision, il est essentiel d'installer un outil pour tester la montée en charge du serveur. Il est important d'utiliser ces outils lors de développement Java EE afin de simuler la charge et d'en mesurer l'impact et les conséquences afin de valider les choix de développement, les pages de code...

Par exemple, lors du développement d'une application Java EE de gestion et de traitement d'images, il sera nécessaire de bien vérifier que lors de l'appel par 100 utilisateurs en simultané, le serveur peut répondre dans un délai raisonnable, que l'application ne va pas saturer la mémoire allouée au serveur... De même, lors d'un choix de conception sur un composant de programmation, l'outil de test pourra nous permettre de valider les librairies, logiciels ou architectures (ex : JDBC ou Hibernate). Il existe plusieurs outils sur le marché pour les tests de montée en charge, tels que l'outil LoadRunner de Mercury et le logiciel libre Apache JMeter.

Apache JMeter

JMeter est un outil écrit en Java et développé par la fondation Apache. JMeter peut générer des tests sur les serveurs Web HTTP et HTTPS, des bases de données avec JDBC, des annuaires et des serveurs FTP. JMeter fournit enfin un ensemble d'outils pour collecter et mesurer les résultats des tests. Du point de vue de la programmation, il pourra analyser plusieurs types de ressources comme des fichiers Java, des Servlets et pages JSP. Apache JMeter est 100 % Java, il requiert donc juste une machine virtuelle Java pour fonctionner et lancer les tests.

JMeter peut être installé sur la même machine que le serveur d'applications, mais afin de ne pas fausser les tests, il vaut mieux éviter d'exécuter JMeter et Tomcat sur les mêmes machines.

L'installation de JMeter est simple, il faut télécharger les fichiers binaires de JMeter sur le site http://jakarta.apache.org/jmeter. Il y a une archive au format .zip pour Windows et .gz pour Linux. L'installation nécessite simplement la décompression de l'archive dans un répertoire du système. Il est bien sûr indispensable d'avoir installé au préalable un JRE ou JDK correctement avec la variable d'environnement JAVA_HOME paramétrée.

Pour lancer JMeter, il faut utiliser le script /bin/jmeter.bat ou l'exécutable /bin/jmeter.exe sous Windows et la commande /bin/jmeter sous Linux.

Il est possible d'ajouter des librairies à JMeter pour tester des connexions JDBC par exemple. Pour cela, il suffit de copier la librairie dans le répertoire /lib et /lib/ext de JMeter.

Si JMeter détecte une erreur, celle-ci sera écrite dans le fichier de log appelé /log/jmeter.log. Ce fichier est créé au lancement de l'application. Le fichier de configuration de JMeter pour SSL, proxy et utilisateurs est /bin/jmeter.properties.

Utilisation

Au démarrage de l'interface, le plan de tests (Test Plan) et le plan de travail (WorkBench) sont affichés. Un plan de test permet de décrire la série de tests à exécuter par JMeter. Pour ajouter ou supprimer un plan de tests, il faut faire un clic droit dans l'explorateur. Il est également possible de charger des éléments de tests présents dans un fichier. Un plan de tests est sauvegardé au format JMX. Un plan de travail contient les éléments qui ne sont pas utilisés par le plan de tests, il s'agit d'un espace de stockage temporaire.

Avant de commencer l'écriture d'un plan de tests, il est nécessaire de configurer le serveur et les ressources dans des conditions qui soient le plus proche possible d'un environnement en production. Il faut donc paramétrer correctement la mémoire allouée, le serveur Tomcat, les connecteurs aux bases de données...

Un plan de tests consiste à tester la montée en charge du serveur en simulant des accès distants.

Il existe plusieurs étapes essentielles pour la construction d'un plan de test :

- Définir le groupe de threads qui simulent le nombre de requêtes en direction du serveur. Un thread est en fait un utilisateur potentiel qui navigue sur le site en production.

- Écrire la configuration du serveur en précisant le nom de la machine en production, le port à utiliser, le protocole...

- Écrire les requêtes HTTP à invoquer par les utilisateurs.

- Ajouter un ou plusieurs composants de mesure JMeter qui va (ou vont) analyser et traiter les réponses sur la charge.

- Enregistrer le plan de tests et le lancer.

Créer un plan de tests

La première étape consiste à créer les utilisateurs (Threads) qui vont envoyer des requêtes au serveur. Nous allons créer par exemple 5 utilisateurs qui vont envoyer des requêtes à 2 pages du site, 2 fois de suite. Il y aura donc au total : 5 utilisateurs * 2 pages * 2 appels = 20 requêtes.

Utilisateur

Il faut ajouter un groupe d'utilisateurs (ThreadGroup) à notre plan de tests.

Nous faisons un clic droit sur le plan de tests et l'action Ajouter Groupe de Thread.

L'écran affiché permet de configurer le nombre de Threads ainsi que l'intervalle de temps pendant lequel ils seront démarrés. La propriété Nombre de Threads (Number of Thread) correspond au nombre d'utilisateurs, dans notre exemple : 5. La propriété Période de chauffe (Ram-Up) définit le nombre de secondes entre le déclenchement de chaque utilisateur. En positionnant à 0, JMeter va démarrer tous les utilisateurs en même temps et donc simuler des accès simultanés au serveur d'applications. Enfin, la propriété Compteur de Boucle (Loop-Count) permet d'indiquer le nombre de boucles à effectuer sur le serveur. Nous positionnons cette propriété à 2 pour effectuer 2 répétitions. Il est aussi possible de rejouer cette séquence à l'infini en cochant la case appropriée.

Configuration du serveur

La seconde étape consiste à préciser le serveur d'applications qui sera utilisé pour les tests.

Il faut d'abord sélectionner le groupe de Thread dans le plan de tests. Puis après un clic droit sur cet élément, les choix Ajouter (Add) Elément de Configuration - Requête HTTP Request par défaut sont sélectionnés.

Les valeurs à préciser sont le protocole utilisé, le nom de domaine du serveur ou son adresse IP et le numéro de port de celui-ci. Des paramètres aux requêtes peuvent être également ajoutés. Dans ce cas, ils seront transmis avec toutes les requêtes en direction du serveur.

Écrire les requêtes utilisateurs

Lors de cette troisième étape, il est temps d'écrire les requêtes HTTP, l'objectif étant de simuler la navigation d'un utilisateur sur le site en production.

D'après notre plan de tests, il faut utiliser deux requêtes HTTP. La première pour la page d'accueil du site http://127.0.0.1:8080/index.jsp et la seconde vers une page d'aide http://127.0.0.1:8080/aide.jsp.

JMeter va donc envoyer les requêtes dans l'ordre où elles apparaissent dans l'arbre

Pour ajouter une page, il faut faire un clic droit sur notre groupe de Threads dans notre plan de travail et ajouter une requête HTTP.

La configuration du serveur a été réalisée précédemment, il n'y a donc que très peu d'éléments à renseigner. Les éléments indispensables sont la méthode HTTP à utiliser (GET ou POST) ainsi que le nom et le chemin de la ressource. Nous donnons un nom explicite à notre requête (page d'accueil) et nous positionnons le chemin d'accès à la page (/ étant donné que c'est la racine du site).

Nous réalisons ensuite la même opération pour notre seconde page/requête.

Ajouter un écouteur/composant de mesure

Lors de cette étape, il faut ajouter un ou plusieurs écouteurs pour analyser les tests. Pour ajouter un moniteur de résultats, nous réalisons un clic droit sur le groupe de Thread dans notre plan de tests et nous ajoutons par exemple un écouteur graphique. Nous précisons alors un fichier de sauvegarde pour les résultats en utilisant le bouton Parcourir. Le fichier de sortie est au format .jtl.

Enregistrer et lancer le plan de tests

L'enregistrement du plan de tests n'est pas obligatoire mais conseillé. Pour sauvegarder un plan de tests, il faut sélectionner l'item Enregistrer du menu et préciser un nom de fichier .jmx.

Pour lancer l'exécution du plan de tests, il faut utiliser le menu Démarrer (Run). JMeter indique alors avec un petit carré vert lumineux en haut à droite de la fenêtre principale l'exécution des tests. Le rectangle repasse en gris quand les tests sont arrêtés. Après avoir sélectionné Stop, le rectangle vert reste allumé jusqu'à la fermeture de tous les Threads.

Il est possible d'ouvrir le même plan de tests avec plusieurs fenêtres d'analyse sans problème. Il est également possible d'utiliser des boucles infinies pour simuler des accès en temps réel sur une plus grande période.

Les résultats d'analyse peuvent être de toute sorte comme des graphiques, des tableaux de données, des arbres...

JMeter est un outil très puissant qui permet d'analyser en temps réel la montée en charge d'un serveur. Les résultats graphiques, textuels et sous forme d'arbres sont très précieux en phases de développement et de production.