Séminaire "Expertise Tomcat" : compte-rendu

Mardi 21 janvier se tenait un séminaire d’une demi-journée organisé par SpringSource, sur les différents aspects de l’utilisation de Tomcat en production : déploiement, performance, débuggage et monitoring.
Pour l’occasion, SpringSource avait mis les petits plats dans les grands : récéption dans un grand hôtel à la Défense avec vue panoramique sur Paris et repas gastronomique, et Filip Hanik sur la scène, un des principaux committers sur Tomcat.

Large scale Tomcat deployment

Pour cette première séance, Filip a montré comment déployer plusieurs instances de Tomcat de manière simple et flexible. Il suffit pour cela de comprendre la différence entre les variables d’environnement CATALINA_HOME et CATALINA_BASE, et le mécanisme de lancement de Tomcat.

Plus, c’est mieux

Mais tout d’abord, pourquoi voudrait-on lancer plusieurs instances de Tomcat sur une machine ?
Selon Filip, il est plus intéressant d’héberger chaque application sur une instance dédiée :

  • Pour éviter que les fuites mémoire d’une application ne contaminent les autres
  • Parce que les ressources consommées et le temps de lancement additionnels sont négligeables
  • Pour définir des paramètres distincts par application (réglages mémoire, répertoire de log, port d’écoute…)
  • Parce qu’il vaut mieux lancer deux JVM avec 2Go de Heap qu’une seul avec 4Go, à cause du garbage collector.

La mystérieuse histoire de CATALINA

Si l’on connaît bien la variable d’environnement CATALINA_HOME, qui est décrite dans la documentation, CATALINA_BASE est en revanche généralement méconnue. Leur combinaison est pourtant très utile :

  • CATALINA_HOME représente le répertoire d’installation de Tomcat, contenant les éléments communs aux instances (server.xml, webapps…). Pour une installation mono-instance, il s’agit du répertoire obtenu par décompression de l’archive d’installation ; mais il est également possible de séparer les binaires (spécifiques à chaque version) de la configuration, comme dans l’exemple ci-dessous.
  • CATALINA_BASE pointe sur un répertoire contenant la configuration spécifique d’une instance de Tomcat. Toutes les valeurs spécifiées ici remplacent celles par défaut (nous verrons comment plus loin).

Exemple de configuration :

 /opt/tomcat/run.sh /opt/tomcat/tomcat-6.0.18   +-- bin : startup.sh, shutdown.sh   +-- shared   +-- lib /opt/tomcat/shared (CATALINA_HOME)   +-- conf : logging.properties, server.xml, tomcat-users.xml...   +-- webapps /opt/tomcat/instance1 (CATALINA_BASE)   +-- bin : setenv.sh, setclasspath.sh   +-- conf : catalina.properties   +-- logs   +-- work /opt/tomcat/instance2 (CATALINA_BASE)   +-- bin : setenv.sh, setclasspath.sh   +-- conf : catalina.properties   +-- logs   +-- work

La gestion (lancement/arrêt) des instances est confiée au script run.sh. En fonction du paramètre « numéro d’instance » qui lui est passé, il positionne la variable d’environnement CATALINA_BASE puis appelle les scripts standards de Tomcat. On peut ainsi mettre à jour les binaires de Tomcat sans pour autant toucher à sa configuration, et ajouter ou supprimer des instances facilement.

Bien démarrer son tigre, mode d’emploi

Voyons maintenant le processus de lancement de Tomcat.
Dans le répertoire bin, se trouvent les scripts startup.sh et shutdown.sh, qui délèguent le travail à catalina.sh. Après avoir détecté son environnement d’exécution (AS400, Cygwin, VMWare…), celui-ci recherche et exécute les scripts setclasspath.sh et setenv.sh dans CATALINA_BASE/bin s’ils existent, sinon dans CATALINA_HOME/bin. C’est là l’occasion de redéfinir, globalement ou par instance, des variables comme JAVA_HOME, JAVA_OPTS ou CATALINA_OPTS.
Au démarrage, Tomcat lit sa configuration est lue depuis les fichiers server.xml, logging.properties, etc. Chaque instance possédant ses propres paramètres (port d’écoute, répertoire de log…), il pourrait être tentant de copier et modifier ces fichiers manuellement.
Mais Tomcat propose une solution plus élégante : les placeholders, ou variables de remplacement. Il est alors possible de créer un modèle universel de configuration possédant des portions dynamiques de la forme « ${variable}« , dont les valeurs spécifiques sont redéfinies au niveau de chaque instance.
Dans notre exemple d’installation, les fichiers de configuration placés dans CATALINA_HOME/conf sont les modèles, et les valeur spécifiques sont définies dans les fichiers CATALINA_BASE/conf/catalina.properties des instances.

Performance Tuning : Harder, Better, Faster, Stronger

En introduction de cette séance, Filip a surpris tout le monde en indiquant qu’il ne voyait pas l’intérêt de la réplication d’état entre serveurs.
Son raisonnement est simple : si vous avez une architecture simple qui fonctionne à 99.99% du temps, il est stupide de mettre en place des systèmes complexes et coûteux pour espérer gérer les 0.01% restants. Au pire, si un serveur montre des signes de faiblesse, il est possible de le drainer avec un load-balancer HTTP, puis de le retirer du cluster sans perdre de requêtes…
Maintenant que plusieurs instances sont lancées, voyons comment les optimiser.

Le processus

Comme toute tentative d’optimisation, le processus est simple :

  1. Définir un objectif quantifiable
  2. Mesurer l’existant
  3. Améliorer
  4. Mesurer l’amélioration
  5. Retour au point 2

Pour l’amélioration, le hardware étant nettement moins cher que les compétences informatiques, il faut toujours tenter en premier d’ajouter de la puissance CPU et/ou de la RAM, et vérifier si cela suffit à atteindre les objectifs fixés. Aujourd’hui, un développeur expérimenté coûte environ 600€/jour ; au DSI de choisir entre une semaine d’optimisation manuelle aux résultats incertains et un nouveau serveur…

Quelques pistes d’optimisation

Plus de 90% du temps de réponse à une requête étant consommés par les applications (accès à une base de données, application de règles métier, préparation des vues…), il est impératif d’optimiser celles-ci avant de commencer à modifier Tomcat.
Voici tout de même les pistes d’optimisation les plus courantes.

Logging

Comme l’avait indiqué Mark Thomas à l’occasion des Rencontres Spring, les logs sont souvent mal configurés. Tout d’abord, supprimez le logger « console » (dans logging.properties), car il est synchrone et ne fait que dupliquer les informations déjà présentes dans les logs des applications. Ensuite, définissez une politique de rotation des fichiers, par jour ou par taille.

Connecteur

Le connecteur utilisé a également son importance. Trois connecteurs existent :

  • BIO : Standard, le plus ancien. Synchrone, stable mais gère SSL via JSSE qui est lent.
  • APR : Natif, asynchrone, gère SSL via OpenSSL qui est rapide.
  • NIO : Utilise java.nio. Asynchrone, mais moins stable et utilise également JSSE.

Le choix de l’un ou l’autre dépend donc :

  1. de la configuration réseau : les load-balancers opèrent-ils couche 4 (TCP) ou couche 7 (HTTP) ?
  2. de la sécurisation HTTPS dans l’application.
  3. de la configuration du paramètre « keep-alive » des connexions.
  4. du niveau de stabilité souhaité

Récapitulatif :

 But                        Bon   Moyen Mauvais Stabilité                  BIO   APR   NIO SSL                        APR   NIO   BIO Faible charge              BIO   APR   NIO Forte charge - Keep-Alive  BIO   APR   NIO Forte charge + Keep-Alive  APR   NIO   BIO
Ressources statiques

Il est souvent intéressant de placer des serveur Apache HTTPD devant les serveurs d’applications, car ils sont généralement plus performants pour servir les ressources statiques (images, scripts javascript…). Mais dans le cas où ces ressources sont de taille modeste (c’est-à-dire inférieure à la taille du buffer de réponse de Tomcat), Tomcat offre des performances équivalentes.
Il peut également être intéressant de jouer sur la taille du cache des données statiques, et sur leur délai de revalidation.

Taille du buffer de réponse

Ce buffer (socketBuffer) joue un rôle particulièrement important dans les performances de Tomcat. Selon Filip, les gains de performance réalisés en déterminant sa taille optimale peuvent représenter jusqu’à 80% des gains totaux réalisés lors du procesus d’optimisation !

Autres réglages

Quelques autres pistes d’optimisation :

  • Nombre de threads (maxThreads) : 400 est une bonne première approximation. Si le CPU encaisse la charge, augmentez la valeur.
  • Nombre de connexions maintenues (maxKeepAlive) : mettre -1 (pas de keep-alive) en l’absence de SSL, si la charge est forte, ou si les load-balancers opèrent sur la couche 4 (TCP) ; sinon, une première valeur entre 100 et 200 paraît raisonnable.
  • Timeout (connectionTimeout): la valeur par défaut (20s) était adéquate pour les connexions RTC, mais en ces temps de haut débit, elle peut être dsecendue à 4s sans problème.

Troubleshooting in production

Pour cette troisième séance, Filip a démontré comment on pouvait diagnostiquer les problèmes en production, sans arrêter les serveurs.
La technique consiste à générer et analyser des thread dumps, avec :

  • kill -3 <pid>
  • jstack -l

Filip a présenté trois cas pratiques :

  • Un deadlock, repéré en suivant les locks obtenus par les différents threads.
  • Un cas de lenteur applicative résultant de la création de trop nombreux objets temporaires : la zone « young » de la mémoire étant pleine, le garbage collector passait plus de 100 fois par seconde, laissant ainsi peu de CPU pour l’application.
  • Un cas de paralysie totale due à une surcharge d’objets non temporaires. Tous les threads étaient bloqués sur des opérations de création d’objet (<init>), et le garbage collector ne parvenait même plus à libérer de la mémoire, mais ne déclenchait pas d’OutOfMemoryError pour autant. Dans ce cas de figure, l’option « -XX:+UseGCOverheadLimit » permet de brider un peu le garbage collector et de récupérer du CPU pour l’application (et la JVM).

La démonstration étant très visuelle et interactive, je ne peux vous en faire un compte-rendu plus détaillé… Mais c’était tout de même assez impressionnant. L’analyse des thread dumps est définitivement une compétence intéressante à acquérir.

Enterprise capabilities

Pour finir, SpringSource TC Server nous a été présenté.
Il s’agit tout simplement d’un Tomcat auquel ont été rajoutées des capacités de gestion et de supervision. Contrairement à SpringSource DM Server, il s’agit d’une version « normale » de Tomcat (la dernière version stable), vos applications ne nécessitent donc aucune modification. De plus, sa configuration est pré-optimisée : logging asynchrone, timeouts, etc.
TC Server collecte en permanence des statistiques comme les temps de réponse, le nombre de connexions réussies ou ratées aux bases de données, les passages du garbage collector… Ces informations sont inestimables en cas de problème, car elles en donnent le contexte sans avoir besoin de reproduire l’erreur.
Enfin, une console d’administration impressionnante, véritable centre de commande, permet de superviser tout un cluster, d’en modifier la configuration (et revenir à la dernière version stable connue si nécessaire), de programmer des déploiements…
Pour finir, un officiel Spring a indiqué que TC Server passerait en version beta dans les semaines à venir, et que le coût du support serait de 500 à 750 € par CPU physique, ce qui est plus que raisonnable au regard du racket de la politique d’IBM par exemple.

Conclusion et Photos

Ce séminaire fut très instructif. Tomcat, le « petit » serveur, possède des ressources insoupçonnées, et son grand frère TC Server pourrait bien être le best-seller de 2009, si la crise se poursuit et pousse les DSI à envisager des solutions alternatives aux grands éditeurs logiciels.
Vous pouvez télécharger tous les slides et démonstrations.

7 réflexions sur “Séminaire "Expertise Tomcat" : compte-rendu

  • 30 janvier 2009 à 17 h 52 min
    Permalien

    Merci pour ce retour, je n’ai pas pu aller à ce rendez-vous interessant.

    > “son grand frère TC Server ”
    tu voulais surement dire “son petit frère TC Server “, car il est né bien bien après 🙂

    Kmwr

    Répondre
  • 30 janvier 2009 à 17 h 52 min
    Permalien

    Merci, Cela complète mes notes 🙂
    D’autant plus que les slides promises par l’orateur ne sont toujours pas arrivées dans ma BAL

    Répondre
  • 30 janvier 2009 à 17 h 54 min
    Permalien

    “Filip a surpris tout le monde en indiquant qu’il ne voyait pas l’intérêt de la réplication d’état entre serveurs.”
    => façon élégante de ne pas positionner Tomcat sur un marché ou il n’est pas adapté/compétitif? 🙂

    “ce qui est plus que raisonnable au regard de la politique d’IBM par exemple.”
    => Selon mon expérience, un client WebSphere aujourd’hui n’est pas prêt à se limiter à un web container. Sinon pour des raisons techniques (dépendances diverses) au moins pour des questions politiques: comment expliquer qu’on n’a plus besoin aujourd’hui de ce qu’on a justifié et acheté hier? Il y du choix Open Source Java EE (à des prix similaires) avant d’en arriver à se replier sur Tomcat.

    Bien sûr il y a tous ceux qui ont déjà du Tomcat, mais auront-ils besoin d’un support dont ils se sont passés jusque là? SpringSource n’est pas le premier à tenter de “monétiser” Tomcat….

    -Alexis (Sun/GlassFish)

    Répondre
  • 30 janvier 2009 à 17 h 55 min
    Permalien

    Concernant la réplication, le couple Tomcat (ou TC Server) + Terracotta est un concurrent très sérieux (et opensource) aux mécanismes de réplication propriétaires de Websphere, Weblogic et Glassfish, et possède même quelques avantages propres.

    Et en ce qui concerne les investissements, il est certes difficile de se dédire après des investissements massifs, mais un client possédant un vieux serveur J2EE risque de réfléchir lors d’une migration : vaut-il mieux passer à JavaEE 5 et porter les EJB2 vers les EJB3, ou passer directement à Tomcat+Spring ?

    De toute façon, rien n’est tranché, et les deux stacks techniques continueront longtemps à cohabiter…

    Répondre
  • 30 janvier 2009 à 17 h 56 min
    Permalien

    Terracotta est impressionnant. L’intégration avec GlassFish (une alternative au clustering traditionnel du produit) est récente mais déjà utilisée en prod à priori.

    Inutile de passer à Java EE5/EJB3 pour se séparer d’un websphere ou un weblogic. Heureusement! C’est éventuellement une deuxième étape. La première est de changer de moteur sans toucher l’appli (ou le moins possible).

    Répondre
  • 30 janvier 2009 à 17 h 56 min
    Permalien

    Il existe deux autres outils gratuits (sans passer par la case SpringSource) et production-ready pour surveiller ce qu’il se passe sur votre Tomcat : JMX et MessAdmin (http://messadmin.sourceforge.net). Indispensables à mes yeux !

    Répondre
  • 9 février 2009 à 10 h 10 min
    Permalien

    Mais tout d’abord, pourquoi voudrait-on lancer plusieurs instances de Tomcat sur une machine ?

    Une autre raison peut aussi etre du au fonctionnement international, 10 instances pour l’europe, 10 pour l’amerique du nord ….. quand je dis 10, je suis pas genereux.
    Comment fait Apple pour iTunes Music Store ?
    http://lists.apple.com/archives/webobjects-dev/2008/Apr/msg00869.html

    Répondre

Répondre à Jer Ba Annuler la réponse.

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.

%d blogueurs aiment cette page :