Accueil > Java > Considérations sur le Déploiement d’Applications J2EE

Considérations sur le Déploiement d’Applications J2EE

Par Allen Chan, le 11/06/2003

Traduit par Olivier, le 20/06/2003

1 Introduction

Si vous discutez avec n’importe quel développeur J2EE aujourd’hui, nombreux sont ceux qui vous parleront en détails des différents types d’EJB ou comment utiliser JMS pour envoyer et recevoir des messages asynchrones. Cependant il sera plus difficile de trouver quelqu’un qui puisse vous décrire une architecture de déploiement qui puisse assurer la montée en charge, une fiabilité et de bonnes performances. Une des raisons de ce manque de compréhension chez de nombreux développeurs est que les spécifications J2EE offrent peu de détails sur le déploiement d’applications, laissant la plupart de l’implémentation à chaque vendeur. Ceci est source de confusion, car chaque vendeur opte pour sa propre façon de déployer les applications J2EE. Dans cet article, nous proposerons dabord les différents modules J2EE et les différentes structures de paquetage. Après cela, nous verrons différentes possibilités d’architectures de déploiement et les problèmes à prendre en compte pendant le design et l’implémentation d’une application J2EE.

Nous considérons pour cet article que vous avez un minimum de connaissances sur les technologies J2EE et que vous êtes à l’aise avec les technologies servlets, JSP, EJB et XML. Pour avoir plus de détails sur les spécifications J2EE, visitez le site J2EE de Sun.

1.1 Modules J2EE

J2EE 1.3 supporte la mise en paquetage d’applications J2EE en différents modules déployables. Il existe deux familles de modules J2EE :

  • Les modules d’application (d’entreprise ou web)
  • Les modules autonomes (EJB ou adapteur de ressource)

En gros, une Archive d’Application Web (fichier WAR) est utilisée pour déployer une application de type web. Ce fichier peut contenir des servlets, des fichiers HTML, des JSPs, et toutes images et fichiers de ressources associées. Alors qu’une Archive d’Application Entreprise (fichier EAR) est un meta-conteneur et peut contenir des EJBs, des adapteurs de ressources et un ou plusieurs modules d’application web. Il est important de considérer lors de la création du paquetage d’applications d’entreprise le nombre de fichiers EAR qu’une application devrait utiliser : dois-je inclure tous mes EJBs dans une seule EAR, ou les placer chacun dans un fichier EAR distinct ? Cette décision peut avoir un impact sur les performances, la montée en charge et la maintenabilité de votre application. Nous discuterons de ceci plus loin. Pour plus de détails sur les types de modules individuels, référez-vous aux spécifications J2EE 1.3 (PDF).

1.2 Les Relations entre ClassLoader

Un domaine qui est souvent regardé avec légerté pendant le design d’une application J2EE sont les relations du ClassLoader entre les différents types de modules. La Machine Virtuelle Java (JVM) utilise le ClassLoader pour localiser et charger les objets Class en mémoire. Par défaut, le SystemClassLoader utilisera le chemin d’information spécifié dans la variable d’environnement CLASSPATH pour localiser les classes. Il est possible qu’une application fournisse son propre ClassLoader, un exemple très connu étant l’URLClassLoader utilisé par le moteur de Servlet pour localiser et initialiser les classes depuis une URL.

En fonction des implémentations des serveurs d’applications J2EE, il existe au moins 3 niveaux de ClassLoader :


Figure 1. Les relations du ClassLoader.

Comme illustré en Figure 1, le serveur d’application utilise le SystemClassLoader et ne verra que les ressources sur le CLASSPATH du système. Il existe un ClassLoader séparé pour chaque modules EAR, RAR et WAR. Les relations exactes de ces ClassLoaders ne sont pas clairement définies, mais il existe typiquement une relation parent-enfant entre les 4 différents ClassLoaders, dans laquelle le ClassLoader enfant sera capable de localiser les classes qui sont visibles dans le ClassLoader de son parent, mais l’inverse n’est pas vrai. Dans le cas de J2EE, le SystemClassLoader est le parent de tous les Classloaders EAR, où un ClassLoader EAR est le parent du ClassLoader WAR et RAR des fichiers WAR et RAR inclus.


Figure 2. Les relations parent-enfant du ClassLoader.

D’après les spécifications Java, un enfant ClassLoader doit dabord utiliser le ClassLoader de son parent pour localiser les classes avant d’utiliser le sien. Ceci peut apparaitre peu intuitif de prime abord, mais nécessaire pour prévenir toute ambiguité et conflit lorsqu’il existe plusieurs ClassLoaders dans une même JVM. Certains serveurs d’applications vous proposent de modifier ce comportement de rechercher du ClassLoader du EAR ou WAR, mais cela n’est recommandé, car il peut conduire à d’autres types de problèmes (par exemple, des ClassCastException peuvent apparaitre si vous avez deux versions d’une même classe dans différents ClassLoaders).

La restriction de visibilité entre les différents ClassLoaders affectera le choix que vous pouvez faire lorsque vous créerez le paquetage de votre application J2EE, spécialement si vous utilisez des ressources et des librairies.

2 Architecture de Déploiement

Une application d’entreprise trois tiers typique est organisée en trois couches principales :

  • La couche présentation : cette couche est responsable de gérer l’interaction avec les utilisateurs.
  • La couche métier : cette couche joue le rôle d’un serveur qui répond aux requêtes effectuées par les utilisateurs au niveau de la couche présentation.
  • La couche données : cette couche comprend la base de données et tous les composants qui sont responsables d’y accéder.

Dans une solution d’entreprise à grande échelle, chaque couche sera déployée dans des domaines séparés pour permettre à chaque domaine de monter en charge de façon indépendante en fonction des besoins du moment. De plus, des répartiteurs de charge peuvent être déployés en amont de la couche présentation pour améliorer la disponibilité et améliorer le basculement en cas de crash. Les couches métier et données s’appuient en général sur la technologie de clusters (grappes) pour pallier au crash. Le diagramme suivant met en évidence une architecture de déploiement de base :


Figure 3. Architecture de Déploiement Trois-tiers Classique.

Selon les cas d’utilisation, il peut y avoir des variations par rapport à cette architecture.

Pour une application J2EE, la couche présentation est en général gérée par des servlets et des JSPs, qui peuvent être mis dans un ou plusieurs paquetages WAR. La couche métier est généralement gérée par des beans sessions (avec ou sans attributs), qui peuvent être mis dans un ou plusieurs paquetages EAR. La couche données est généralement gérée par des beans entités (qui contrôlent l’accès à la base de données) ou des adapteurs de ressources (qui contrôlent l’accès aux systèmes plus anciens), qui peuvent être mis en paquetage en un ou plusieurs fichiers EAR. Le diagramme suivant montre la même architecture de déploiement avec des ressources et modules J2EE spécifiques :


Figure 4. Architecture de Déploiement d’une Application d’Entreprise Java.

Déployer une application J2EE fondée sur ce type de structure offrira la plus grande flexibilité, mais il existe d’autre considérations qui entrent en jeu avant que l’architecture de déploiement ne soit finalisée.

2.1 Considération sur les Performances

Tout le monde sait que l’appel de procédures distantes est plus coûteux que leur appel local. Au cours d’un appel de procédure à distance, les objets du proxy local doivent effectuer une copie de tous les arguments et les envoyer le long de la connexion, par RMI, aux objets distants, ce qui résulte en un accroissement du trafic réseau et des temps de réponse plus longs. Considérez un scénario où les utilisateurs envoient des commandes depuis les pages web, qui à leur tour invoquent des servlets qui invoquent le traitement des méthodes métiers au niveau des beans sessions et entités. Au moins quatre opérations réseaux sont effectuées, deux desquelles sont des appels distants aux EJB :


Figure 5. Séquence d’Appel à Distance dans une Traitement Métier Classique

Au cas où un bean session doit faire appel à d’autres beans sessions ou d’autres beans entités, d’autres appels à distance seront effectués. Si les performances sont votre priorité, des ajustements doivent être effectués dans l’architecture et le design pour réduire le nombre d’appels à distance, ou réduire le coût d’un appel distant.

Il existe plusieurs façons de résoudre le problème des performances :

  1. Nous pourrions réduire le nombre de transactions effectuées sur le réseau en utilisant un modèle objet de plus grosse “granularité” pour les EJB.
  2. Nous pourrions éliminer quelques appels distants en utilisant des interfaces locales, plutôt que distantes, pour les beans entités.
  3. Nous pourrions modifier quelques appels distants en appels locaux en changeant la structure de paquetage pour placer un plus grand nombre de beans dans un EAR.

2.1.1 Granularité EJB

Si les interfaces d’accès ont une granularité trop fine, il en résulte un trafic excessif et une longue attente. Il faut réfléchir à l’architecture et au design pour s’assurer que le bon niveau de granularité est utilisé. Il existe plusieurs “design patterns” pour J2EE qui permettent de controler la granularité. Les plus utilisés sont le TransfertObject et la Façade. Puisque le but de notre discussion est le déploiement et le paquetage, veuillez vous référer au site du modèle J2EE pour mieux connaitre ces patterns.

2.1.2 Interfaces Locales contre Distantes

J2EE introduit le concept de beans entreprise locaux. Ceci permet à un bean entité d’exposer une interface locale, permettant ainsi le passage de paramètres par référence plutôt que par valeur. Cependant pour qu’un bean session puisse accéder à l’interface locale des beans entreprises, les beans entreprises locaux doivent être contenus dans le même ficher EAR que le bean session. Il existe deux manière d’aboutir à cela :

  • Créer une Façade Session au devant des beans entités dans la couche données. Ceci permet d’exposer l’interface des fonctions des beans entités aux applications externes. Cependant, selon la granularité de la Façade Session, le gain de performance ne sera pas forcément important.
  • Placez les beans entités dans la couche métier et faites en sorte que les beans sessions de cette couche puissent accéder aux beans entreprise locaux directement. Cette méthode réduit la réutilisabilité des beans entités. Puisque le bean entité local est uniquement accessible pour les beans qui sont situés dans le même fichier EAR, les autres beans métiers qui résident en dehors de ce module d’application ne pourront pas y accéder. Les capacités de montée en charge de l’application sont également réduites du fait que le bean entité local est maintenant lié au même conteneur J2EE que la couche métier.

2.1.3 Structure de Paquetage

Certains serveurs d’applications J2EE (comme WebLogic de BEA) sont capables d’optimiser les appels entre beans (voir le Document de Référence WebLogic sur le Chargement de Classes) en appels locaux si les beans se trouvent dans la même application entreprise. Ceci est spécialement bénéfique si un bean session fait appel à plusieurs beans sessions ou entités. Il y a également des problèmes avec cette approche :

  • Maintenabilité réduite. Tous les beans mis en paquetage dans le même EAR doivent être déployés et redéployés en même temps. Ceci réduit la possibilité de mettre à jour qu’un seul bean à chaud.
  • Dépendance vis-à-vis de la plateforme. Ce type d’optimisation n’est pas permis avec tous les serveurs d’applications, et pourrait n’avoir aucun effet si vous en changez.
  • Remise en cause des méthodes de design. De nombreux développeurs définissent leurs beans en considérant que tous les paramètres seront passés par valeur et non pas par référence. Changer les conventions d’appel pourrait aller à l’encontre de cette hypothèse, spécialement si le pattern TransfertObject est utilisé en coordination avec des beans entités gérés par BMP.

2.2 Considération sur le Placement des Ressources

Un autre domaine à prendre en compte est le placement des ressources communes et des librairies. Une règle d’or est que la ressource devrait être avec les modules J2EE qui l’utilisent. Cependant, s’il vous arrive d’avoir le cas d’une ressource utilisée par plusieurs modules, vous voudrez peut-être le placer là où il sera accessible par tous les modules. De plus, c’est une mauvaise habitude de mettre les ressources dans votre CLASSPATH parce qu’elles pourraient entre en conflit avec d’autres modules J2EE déployés dans le même conteneur. Ceci limitera également vos possibilités de déploiement à chaud.

2.2.1 Les Bundles de Ressources (et Autres Types de Ressources Statiques)

Considérons un moment qu’il existe un fichier .properties (un bundle de ressource) qui contient des informations qui sont utilisées par plusieurs applications web. A cause de la relation d’héritage du ClassLoader et le niveau d’isolation, il existe trois façons de placer ce fichier :

  1. Mettre une copie des bundles de ressources dans le répertoire WEB-INF/classes de chaque fichier WAR. L’inconvénient de cette approche est que si une modification doit être apportée plus tard, elle doit être apportée dans chaque fichier des WAR. Ceci est évidemment source d’erreurs.
  2. Placer le fichier de bundles dans un répertoire spécifié par le CLASSPATH système. Ceci résoud le premier problème de la nécessité d’effectuer de multiples modifications sur le fichier. Cependant, cette approche limite également les options de redéploiement, étant donné que les ressources chargées par le SystemClassLoader ne peuvent être rechargées qu’après un redémarrage de la JVM. Dans ce cas, les modifications que vous faites sur les ressources ne seront prises en compte qu’au redémarrage de l’application serveur. Pour des solutions J2EE où le niveau de disponibilité est très élevé, ceci aura pour effet une maintenance très compliquée.
  3. Placer le fichier de ressources et tous les fichiers WAR qui y sont liés dans le même fichier EAR, en se basant sur le fait que le ClassLoader du WAR peut accéder au ClassLoader du EAR pour les ressources. Cette pratique permet la plus grande flexibilité, étant donné qu’il n’y a maintenant qu’un endroit où mettre à jour les ressources. La mise à jour prendra effet immédiatement si l’application est redéployée (si le serveur d’application supporte le redéploiement à chaud de fichier EAR). Cependant, pour que chaque WAR puisse localiser la ressource, vous devez mettre le chemin d’accès au fichier de ressources dans le fichier MANIFEST du paquet WAR.

2.2.2 Librairies Tierces

Il n’est pas rare pour un projet J2EE d’inclure des modules de tierce partie qui sont totalement disponibles gratuitements (par exemple, log4j d’Apache). Dans une telle situation, il est préférable de placer les fichiers jar de ces librairies dans un endroit précis dans l’EAR. Les librairies ne devraient être placées dans le CLASSPATH système que si elles n’entrent pas en conflit avec d’autres librairies existantes utilisées par le serveur d’application et si il n’est pas nécessaire de mettre à jour ces librairies trop fréquemment. Si vous décidez de placer les librairies partagées à l’intérieur d’un module EAR, assurez-vous que :

  • Toutes les librairies tierces sont centralisées dans un même endroit (exemple, /lib ou /ext). Cela facilitera la recherche en cas de problèmes en identifiant clairement les composants externes dont les modules dépendent.
  • A cause des restrictions avec les différents ClassLoaders, vous devez indiquer le chemin vers les librairies tierces dans les fichiers MANIFEST des modules J2EE, WAR et EJB compris.

2.3 D’autres Considérations

J2EE autorise le développement de solutions hautement évolutives et disponibles de manière relativement simple. Pour cette raison, l’architecture de déploiement ne peut pas être considérée complète à moins de faire l’étude des besoins sur la montée en charge et la disponibilité.

2.3.1 Montée en Charge

Comme mentionné au début de la Section 2, éclater l’application en plusieurs unités de déploiement sur différentes couches offre la plus grande flexibilité pour le modèle concernant la montée en charge. Cependant, il est nécessaire de faire attention à avoir les bonnes granularité et modularité pour avoir un bon équilibre entre flexibilité et performance.

2.3.2 Maintenabilité et Déploiement à Chaud

Le déploiement à chaud est la possibilité de déployer et redéployer une application d’entreprise sans avoir besoin de stopper et relancer le serveur d’application. Si le déploiement à chaud est nécessaire pour votre application, assurez-vous que les ressources et les librairies tierces utilisées par l’application et d’autres modules d’entreprise sont mises en paquet d’une manière autonome. Eviter d’avoir une dépendence au niveau du CLASSPATH système. Assurez-vous que tout ce qui est nécessaire au module de l’application d’entreprise est mis en paquet dans le même fichier EAR.

2.3.3 Sécurité

Selon les besoins de sécurité de votre application, différents mécanismes de sécurité (SSL, VPN, modèle de sécurité déclarative du module J2EE) peuvent être implémentés entre système tiers pour offrir une sécurité au niveau des méthodes. Bien que les spécifications J2EE décrivent le niveau de sécurité requis par le serveur d’applications, elles ne précisent pas comment la sécurité doit être implémentée ; et donc, la sécurité dépend du revendeur. Si votre application utilise la propagation d’identité de sécurité entre différents domaines de sécurité (dans le cas d’une système de sécurité distribuée), vous devez consulter votre revendeur, car il pourrait exister des restrictions qui limiteront vos choix dans l’architecture de déploiement.

2.3.4 Automatisation du Déploiement

Dans un monde idéal, tous les administrateurs système que vous pourriez rencontrer seraient très familiers avec les serveurs d’applications J2EE. Cependant, il n’est pas rare que bien que votre administrateur système soit un expert UNIX ou Windows, il ou elle ne connait souvent pas grand chose de J2EE. Donc pour le bénéfice de ceux qui déploieront et administreront les applications au jour le jour, il est important d’avoir des étapes de déploiement clairement documentées. Il serait encore mieux d’avoir des scripts de déploiement automatique. Aujourd’hui, de nombreux vendeurs de serveurs d’applications fournissent un moyen de déployer les applications soit par une console d’administration du vendeur ou par la ligne de commande, ou par l’API de Java Management Extension (JMX) (exemple : l’API de Management de Weblogic). Cependant, à cause des différents mécanismes de déploiement utilisés par les différents vendeurs, vous devez créer un script spécifique par plateforme.

3 Directions à Venir

Comme de plus en plus d’applications J2EE sont écrites, il devient crucial que les spécifications J2EE définissent un standard commun pour la mise en paquet et le déploiement des applications. J2EE 1.3 propose des spécifications pour un standard de paquet ; cependant, il n’existe toujours pas de standard pour le déploiement d’applications - c’est là qu’une initiative comme JSR 88 (l’API de déploiement J2EE) vient à point.

Le but de cette JSR est de définir un ensemble API standard qui permettra à tout outil de déploiement de déployer n’importe quel module J2EE sur un serveur d’application compatible J2EE. Plus précisément, le standard doit répondre aux points suivants :

  • Installation : possibilité de déployer un composant pré-empaqueté vers le conteneur.
  • Configuration : possibilité d’utiliser une mécanisme standard de configuration pour récupérer les données de configuration.
  • Suppression des modules déployés : possibilité de retirer un module J2EE déployé sur le conteneur.

La JSR sera incluse dans les spécifications J2EE 1.4. Avec cette nouvelle API, un vendeur d’applications pourra maintenant créer des outils de déploiement ou des scripts qui pourront automatiquement déployer ses applications vers différents serveurs d’applications sans avoir à se soucier des différences entre les fonctions de déploiement. Cependant, il y a toujours des points qui ne sont pas adressés par cette JSR :

  • Déploiement et configuration des ressources J2EE : déploiement et configuration de ressources J2EE, telles que pools de connections à une base de données, DataSources, et JMS qui sont toujours très liées aux vendeurs jusqu’à présent.
  • Configuration de sécurité : les modules J2EE supportent un modèle de sécurité déclarative en autorisant la création de roles et de groupes dans le descripteur de déploiement. Cependant, si les informations de sécurité doivent être modifiées au moment du déploiement, l’administrateur système doit encore s’appuyer sur des mécanismes proposé par le vendeur pour effectuer les modifications.
  • Dépendance de modules : bien que les nouveaux standards autorisent la spécifications de dépendance de modules dans le descripteur de déploiement, les dépendances ne sont pas suivies. Ainsi, les ressources qui sont nécessaires au module ne sont pas automatiquement désactivées quand le module est retiré du conteneur.

4 Conclusions

Le déploiement est encore un domaine de J2EE qui n’est pas très connu des développeurs. Si les problèmes de déploiement ne sont pas envisagés durant les phases d’architecture et de design, vous pourriez rapidement aboutir à une situation dans laquelle des modifications d’architecture ou/et de design sont nécessaires. Comme illustré plus haut, il y a plusieurs domaines qui doivent être pris en compte depuis le début pour s’assurer que l’application atteigne les besoins en performance, et disponibilité voulus.

Textes originaux en anglais sur O’Reilly : J2EE Application Deployment Considerations par Allen Chan

opoppon Java , ,

  1. Pas encore de commentaire
  1. Pas encore de trackbacks
S'abonner aux commentaires de cet article