Considérations relatives à la conception d'applications de distributeur de requêtes asynchrones

Le Distributeur de requêtes asynchrones (ARD) n'est pas une solution prête à l'emploi pour la programmation de servlets. Vous devez évaluer les besoins de votre application et tenir compte des remarques (caveat) relatives à l'utilisation du Distributeur de requêtes asynchrones. La commutation de toutes les inclusions sur le démarrage en mode asynchrone n'est pas la solution idéale pour tous les scénarios, mais une utilisation judicieuse du Distributeur de requêtes asynchrone peut améliorer le temps de réponse.

Implémentation du Distributeur de requêtes asynchrones côté client

  • JavaScript est écrit de manière dynamique dans la sortie de réponse.
  • Ce script JavaScript provoque le renvoi des requêtes Ajax à un fournisseur de résultats côté serveur.
  • En raison des fonctions d'entrée-sortie asynchrones (AIO - Asynchronous Input/Output) du canal, la requête Ajax n'attache pas une unité d'exécution, et au lieu de cela, reçoit un avis d'achèvement via un rappel d'inclusion.
  • Le client émet une seule requête à la fois pour les inclusions asynchrones en raison des limites du navigateur relatives au nombre de connexions.
  • La connexion initiale doit être valide pendant toute la durée de vie des inclusions. Elle ne peut pas être réutilisée pour les requêtes Ajax.
  • Des noeuds de commentaire, comme
    <!--uniquePlaceholderID--><!--1-->
    sont placés dans le modèle d'objet de navigateur car les noeuds de commentaire n'ont aucune incidence sur la mise en page.
  • Chaque fois qu'un fragment complet existe, une réponse peut être envoyée au client et le noeud de commentaire associé au même ID est remplacé. Des requêtes sont émises jusqu'à ce que tous les fragments soient extraits.
  • Vérifiez les applications sur tous les navigateurs pris en charge lorsque vous utilisez l'agrégation côté client. L'application des principes JavaScript orientés objet évite que les applications utilisent le nom de méthode getDynamicDataIBMARD. Tout élément window.onload antérieurement indiqué est démarré avant la méthode onload du Distributeur de requêtes asynchrone.

Service de résultats du canal de répartiteur de requêtes asynchrones (ARD)

Les requêtes relatives aux données d'inclusion provenant du code JavaScript asynchrone sont envoyées à des URI (Uniform Resource Identifier) également appelés URL que le canal ARD peut intercepter en vue d'empêcher leur passage par le gestionnaire de requêtes de conteneur web. Ces URI sont uniques pour le redémarrage de chaque serveur.

Par exemple, /IBMARD01234567/asyncInclude.js est l'URI utilisé pour JavaScript qui force l'extraction des résultats, et /IBMARD01234567/IBMARDQueryStringEntries?=12000 est utilisé pour extraire les résultats correspondant à l'entrée associée à l'ID 12000.

Pour empêcher tout accès non autorisé aux résultats, des ID uniques sont générés pour l'URI de service et les entrées du Distributeur de requêtes asynchrone. Un générateur d'ID commun est partagé par la session et le Distributeur de requêtes asynchrones, ce qui permet de configurer le caractère unique des ID lors de la configuration de la session. Les ID de session assurent la sécurisation, mais celle-ci est vraiment garantie par l'utilisation d'un jeton LTPA (Lightweight Third-Party Authentication).

Agrégation personnalisée côté client

Si vous voulez effectuer votre propre agrégation côté client, la méthode isUseDefaultJavascript doit être renvoyée avec la valeur false. La méthode isUseDefaultJavascript fait partie de la méthode AsyncRequestDispatcherConfig, laquelle est définie dans la méthode AsyncRequestDispatcher ou pour la méthode AsyncRequestDispatcherConfigImpl.getRef. La méthode AsyncRequestDispatcherConfigImpl.getRef est l'objet de configuration globale. Vous pouvez souhaiter effectuer votre propre agrégation côté client si la fonction du bouton Précédent ne fonctionne pas correctement. Vous devez retirer les résultats du service de résultats générique afin d'empêcher les fuites de mémoire, ce qui entraîne l'échec des requêtes multiples ayant les mêmes résultats de réponse via XMLHttpRequest. Pour faciliter une localisation correcte de la position, des espaces réservés sont toujours écrits dans le code sous la forme
<!--uniquePlaceholderID--><!--x-->
où x indique l'ordre des inclusions. Pour le noeud final, les résultats sont extraits à partir de l'attribut de requête com.ibm.websphere.webcontainer.ard.endpointURI.
Lorsqu'une requête est émise pour le noeud final, le Distributeur de requêtes asynchrone envoie autant de fragments de réponse que possible. Par conséquent, le client doit émettre à nouveau la requête si tous les fragments n'ont pas été retournés. Toute tentative d'affichage des résultats directement dans un navigateur à l'aide de XMLHttpRequest peut générer des erreurs dues à un XML incorrectement constitué. Les données de réponse sont renvoyées au format suivant avec un type de contenu text/xml :
<div id="2"><BR>Servlet 3--dispatcher3 requesting Servlet3 to sleep for 0 seconds at: 1187967704265 
<BR> Servlet 3--Okay, all done!  This should print pop up: third at: 1187967704281 </div>

Pour plus d'informations sur les interfaces AsyncRequestDispatcherConfig et AsyncRequestDispatcher, voir le package com.ibm.websphere.webcontainer.async dans la documentation sur les interfaces de programme d'application (API). La documentation sur les API générées est disponible dans la table des matières de la documentation, sous Référence > APIs - Application Programming Interfaces.

Agrégation côté serveur

Comme l'agrégation côté client, l'agrégation côté serveur utilise le canal ARD comme service de résultats. Le canal ARD sait quelles inclusions asynchrones ont été effectuées pour un ensemble donné de mémoires tampon. Il est alors possible de rechercher dans ces mémoires tampon un espace réservé d'inclusion. En raison des contingences liées à la mise en mémoire tampon JSP, il se peut que l'espace réservé pour l'inclusion ne se trouve pas dans les mémoires tampon sur lesquelles porte la recherche. Si c'est le cas, les espaces réservés d'inclusion non trouvés doivent être recherchés dans l'ensemble de mémoires tampon suivant. Le Distributeur de requêtes asynchrones tente d'effectuer une agrégation itérative au fur et à mesure que des inclusions sont renvoyées afin que le contenu de la réponse puisse être envoyé au client le plus rapidement possible.

Accès concurrents

Un gestionnaire de travaux est utilisé pour lancer les inclusions. Si le nombre des inclusions faisant actuellement l'objet d'un requête est supérieur à la taille de pool d'unité d'exécution du gestionnaire de travail et que cette taille n'est pas extensible, le gestionnaire lance le travail sur l'unité d'exécution active et ignore la phase d'écriture de l'espace réservé. L'utilisation de Concurrency Utilities for Java™ EE permet la propagation du Java EE de l'unité d'exécution initiale, y compris le contexte de zone de travail, d'internationalisation, de profil d'application, de gestion de la charge de travail du système d'exploitation z/OS, de sécurité, de transaction et de connexion.

Temporisateur

Un temporisateur unique est utilisé pour le Distributeur de tâches asynchrones (ARD) et des tâches de temporisateur sont créées pour tous les types de temporisateur des requêtes ARD. Il est possible que les tâches enregistrées avec le temporisateur ne s'exécutent pas à l'heure précise qui est indiquée, car il se peut qu'il doive attendre l'achèvement d'autres actions associées à un temporisateur. Le temporisateur est utilisé en dernier recours.

Distributeur de requêtes à distance

Le Distributeur de requêtes asynchrones peut être utilisé, facultativement, avec le distributeur de requêtes à distance. Le distributeur de requêtes à distance exécute l'inclusion sur un serveur d'applications différent dans un groupe central en sérialisant le contexte de requête dans un message SOAP et en utilisant les services Web pour appeler le serveur distant. Cela s'avère utile lorsque l'émission de la requête en local prime sur le coût de création et d'envoi d'un message SOAP via les services Web.

Exceptions

Lorsqu'une exception est présente dans un servlet inclus, le conteneur web parcourt les définitions de page d'erreur mappées aux types d'exception. Ainsi, une page d'erreur définie dans le descripteur de déploiement s'affiche comme une portion de la page d'agrégats. Insérez une logique dans la page d'erreur elle-même si le comportement est différent pour une inclusion. Etant donné que l'inclusion est exécutée de manière asynchrone, il n'est pas certain que le servlet de niveau supérieur soit toujours en service, par conséquent, l'exception n'est pas propagée en aval à partir d'une inclusion asynchrone comme une inclusion normale. D'autres inclusions se terminent, ce qui permet d'afficher des pages partielles.

Si le gestionnaire de travail du Distributeur de requêtes asynchrones est à cours d'unités d'exécution de tâche, l'inclusion est traitée comme une inclusion asynchrone. Il s'agit du paramètre par défaut mais le gestionnaire de travail peut également croître de telle sorte que cette condition ne soit plus réalisée. Cette modification du traitement est transparente pour l'utilisateur en cours de traitement mais est notée une fois dans les journaux système sous la forme d'un message d'avertissement, et par la suite, dans les journaux de trace lorsqu'ils sont activés. Les autres états susceptibles de déclencher l'inclusion en mode synchrone sont ceux où le pourcentage maximal de requêtes arrivées à expiration est atteint pendant un intervalle de temps, et où la taille maximale de l'espace de stockage des résultats est atteinte.

Il se peut que des exceptions se produisent hors de la gestion de page d'erreur normale. Par exemple, un travail peut être rejeté par le gestionnaire de travail. Un temporisateur peut expirer alors qu'il attend le retour d'une réponse d'inclusion. Il se peut que le canal ARD, agissant comme un service générique pour extraire les résultats, reçoive un ID non valide. Dans ces situations, il n'existe aucun chemin d'accès à la gestion de pages d'erreur, car le contexte, tel que ServletRequest, ServletResponse et ServletContext, est manquant et la requête ne fonctionne pas. Pour pallier ces difficultés, vous pouvez utiliser l'interface AsyncRequestDispatcherConfig en vue de fournir des messages d'erreur personnalisés. Des valeurs par défaut sont fournies et internationalisées selon les besoins.

Des exceptions peuvent également se produire hors de la portée de la requête sur laquelle la configuration personnalisée a été définie, par exemple sur la requête XMLHttpRequests ultérieure côté client. Dans ce cas, la configuration globale doit être modifiée. L'extraction peut être effectuée via com.ibm.wsspi.ard.AsyncRequestDispatcherConfigImpl.getRef().

Lancement d'une inclusion
Le gestionnaire de travail fournit un délai d'attente pour le lancement d'une inclusion. Ce délai étant généralement fourni de manière instantanée, il ne peut pas être activé à l'aide d'un programme. Il peut cependant être configuré dans les paramètres du gestionnaire de travail. Par défaut, cela ne se produit pas car une vérification du nombre maximum d'unités d'exécution est effectuée avant la planification du travail. Le travail peut être extrait si setRetriable(true) est appelé dans la méthode AsyncRequestDispatcherConfig utilisée.
Fin d'une inclusion
Le délai d'attente initié débute une fois le travail accepté. Il peut être configuré via la console ou à l'aide d'un programme via la méthode AsyncRequestDispatcherConfig.setExecutionTimeoutOverride ; la valeur par défaut est 60000 ms, ou une minute. Le message issu de AsyncRequestDispatcherConfig.setExecutionTimeoutMessage est envoyé à la place des résultats d'inclusion. Si le délai d'attente initié est atteint, mais que les résultats d'inclusion réels sont prêts lorsque les données peuvent être vidées, la préférence est donnée aux résultats réels. De plus, cela ne s'applique pas aux appels insertFragmentBlocking qui attendent toujours jusqu'à l'achèvement de l'inclusion.
Expiration des résultats
Etant donné que les résultats doivent être mis en attente dans un service côté client en vue d'être envoyés pour la requête Ajax, un mode d'expiration des résultats doit être défini si le client s'arrête et ne peut jamais extraire l'entrée. La valeur par défaut d'une minute est suffisante pour une requête classique car la requête Ajax sera réceptionnée immédiatement après l'envoi de la réponse. Le temporisateur peut être configuré à l'aide d'un programme via la méthode setExpirationTimeoutOverride de AsyncRequestDispatcherConfig. Le message généré par la méthode getOutputRetrievalFailureMessage d'AsyncRequestDispatcherConfig est affiché à chaque tentative d'accès à une entrée arrivée à expiration et supprimée de la mémoire cache. Ce message est identique à celui envoyé lorsqu'un utilisateur demande un résultat avec un ID qui n'existe pas.

Inclusions ou fragments

Déterminez quelles opérations peuvent être effectuées de manière asynchrone et à quel moment elle peuvent commencer. Dans l'idéal, toutes les inclusions sont terminées lorsque les appels getFragment sont effectués au début de la requête, ce qui laisse plus de temps pour l'achèvement des inclusions, et limite les opérations de mise en mémoire tampon et d'agrégation lors de l'insertion des fragments. Cependant, il est plus simple d'appeler une inclusion asynchrone, car cette action s'appuie sur le même modèle qu'une inclusion de répartiteur de requêtes classique.

Conteneur Web

ServletContext
Lorsque des inclusions entre contexte sont effectuées, le répartiteur ARD doit également être activé pour le contexte cible car l'application web doit avoir été initialisée pour le répartiteur afin que son contexte de servlet dispose des méthodes valides pour extraire un élément AsyncRequestDispatcher. Le type d'agrégation est déterminé par la configuration de contexte initiale car vous ne pouvez pas mélanger les types d'agrégation.
ServletRequest
Vous devez cloner la requête pour chaque inclusion pour éviter des conflits entre unités d'exécution. Les applications peuvent encapsuler les objets de requête par défaut et vos encapsuleurs doivent par conséquent mettre en oeuvre l'interface com.ibm.wsspi.webcontainer.servlet.IServletRequest, laquelle fournit une méthode de clonage d'objet publique qui créé l'exception CloneNotSupportedException.
Le désencapsulage a lieu jusqu'à ce qu'un encapsuleur de requête implémentant cette interface soit trouvé. Les encapsuleurs qui n'effectuent pas d'implémentation sont perdus ; cependant, un filtre de servlet qui est configuré pour l'inclusion peut réencapsuler la réponse.
Les modifications apportées à ServletRequest ne sont pas propagées vers le servlet de niveau supérieur, sauf si transferState est activé dans AsyncRequestDispatcherConfig et si insertFragmentBlocking est appelé.
ServletResponse
Une réponse encapsulée qui étend com.ibm.websphere.servlet.response.StoredResponse est créée par le répartiteur ARD et envoyée aux inclusions, car la sortie de la réponse doit pouvoir être extraite au-delà du cycle de vie de la réponse initiale.
Les en-têtes internes définis dans des inclusions asynchrones ne sont pas pris en charge en raison des restrictions liées au cycle de vie, sauf si transferState est activé dans AsyncRequestDispatcherconfig et si insertFragmentBlocking est appelé. Les en-têtes classiques ne sont pas pris en charge dans une inclusion synchrone comme indiqué par la spécification de servlet.
Les filtres d'inclusion peuvent réencapsuler la nouvelle réponse et un vidage doit être effectué une fois l'opération terminée.
ServletInputStream
Une application peut lire sans problème des paramètres à l'aide de getParameter. L'analyse syntaxique des paramètres est forcée par la première inclusion asynchrone pour empêcher l'accès simultané au flot d'entrée.
HttpSession
Les appels getSession initiaux qui génèrent un en-tête Set-Cookie doivent être effectués à partir du servlet de niveau supérieur, car il n'est pas possible de prévoir à quel moment les inclusions sont lancées et si les en-têtes ont déjà été vidés. Ce n'est pas le cas lorsque transferState est activé dans AsyncRequestDispatcherConfig et qu'un appel d'insertFragmentBlocking a lieu. Normalement, ceci crée une exception lorsque vous ajoutez l'en-tête.
Filtres
S'il existe un filtre pour une inclusion, ce dernier est généré sur l'unité d'exécution asynchrone.
Inclusions asynchrones imbriquées
Les inclusions asynchrones imbriquées ne sont pas prises en charge car elles rendent l'agrégation plus complexe. Cependant, une inclusion asynchrone peut comporter des inclusions synchrones imbriquées. Toute tentative d'exécution d'une inclusion asynchrone ramène à une inclusion synchrone.

Transactions

Chaque tâche soumise au gestionnaire de travaux est appelée à l'aide de sa propre transaction, comme c'est le cas pour les beans enterprise avec des transactions gérées par conteneur. L'environnement d'exécution lance une transaction locale avant de démarrer la méthode. La tâche peut démarrer sa propre transaction globale si cette dernière est possible pour le composant Java EE appelant.

Si la tâche crée une exception, toutes les transactions globales sont annulées. Si la méthode se termine normalement, toutes les transactions locales en cours se terminent suivant la règle d'action non résolue configurée pour le bean. Si la tâche lance sa propre transaction globale sans parvenir à la valider, celle-ci est annulée lorsque la méthode rend la main.

Gestion des connexions

Une tâche soumise au gestionnaire de travaux peut utiliser les sources de données et les fabriques de connexions que le servlet par lequel elles ont été créées a obtenues à l'aide de références de ressource java:comp. Cependant, la méthode de bean doit accéder à ces connexions à l'aide d'un modèle get-use-close (extraction-utilisation-fermeture). Il n'existe pas de mise en cache des connexions entre les appels de méthode sur une tâche. Les sources de données ou les fabriques de connexions peuvent être mises en cache, mais les connexions doivent être extraites à chaque appel de méthode, puis utilisées et fermées. Bien que la tâche puisse rechercher des fabriques de connexion à l'aide d'un nom JNDI (Java Naming and Directory Interface) global, cela n'est pas recommandé pour les raisons suivantes :
  • Le nom JNDI est codé en dur dans l'application, par exemple, sous forme de propriété ou de littéral chaîne.
  • Les fabriques de connexions ne sont pas partagées car il n'existe aucun moyen de spécifier une portée de partage.
Evaluez les scénarios dans lesquels la charge est élevée car les inclusions asynchrones peuvent augmenter le nombre d'unités d'exécution en attente sur la connexion.

performance

Les inclusions étant terminées en mode asynchrone, les données totales de performance doivent tenir compte des performances des inclusions asynchrones. Antérieurement, le temps total de la requête pouvait antérieurement découler du temps nécessaire à l'achèvement du servlet de niveau supérieur, mais, maintenant, ce servlet prend fin avant l'achèvement des inclusions. Le servlet de niveau supérieur tient toujours compte du temps de configuration supplémentaire requis pour chaque inclusion.

C'est la raison pour laquelle une nouvelle mesure des performances ARD a été ajoutée à la fonction Performance Monitoring Infrastructure afin de mesurer le temps nécessaire à l'achèvement d'une requête sur le canal ARD. La granularité de ces mesures est définie pour le niveau d'URI de requête.

ARD étant une fonction facultative qui doit être activée, aucune baisse des performances n'est observée lorsqu'elle n'est pas utilisée. Cependant, les applications non ARD qui résident sur un serveur d'applications compatible avec ARD seraient affectées négativement par la couche de canal ARD supplémentaire. La couche de canal ne sait pas vers quelle application elle se dirige et c'est la raison pour laquelle elle est activée ou désactivée pour toutes les applications d'une chaîne de canal. Ces applications sont définies par hôte virtuel.

Security

La sécurité n'est pas appelée pour les répartitions d'inclusions synchrones conformément à la spécification de servlet. Cependant, le contexte de sécurité est transmis via Concurrency Utilities for Java EE pour prendre en charge l'utilisation à l'aide d'un programme des méthodes isUserInRole et getUserPrincipal dans ServletRequest. Ce contexte de sécurité peut également être propagé vers une répartition de requête distante à l'aide de la sécurité des Services Web.


Icône indiquant le type de rubrique Rubrique de référence



Icône d'horodatage Dernière mise à jour: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=rweb_ard_considerations
Nom du fichier : rweb_ard_considerations.html