10
votes

Solution au problème de requête de course longue dans une application Web (demande asynchrone)

Voici le problème

Un utilisateur d'une application Web d'entreprise effectue une tâche qui entraîne une longue requête (ou une autre tâche intense de traitement longue)

Problèmes:

  • Demande Timeout - Après un moment, l'utilisateur peut obtenir un délai de requête
  • Délai de session - Si aucune méthode de garde de session n'est utilisée, un délai d'attente de session peut survenir
  • Demande de verrouillage du thread
    • Étant donné que le thread de la demande ne renvoie pas, il peut bloquer de nouvelles réquiales (si elles atteignent la limite de piscine)
    • Dans certains serveurs d'applications, l'état de santé du serveur peut déclencher un redémarrage forcé du nœud ou de l'application (en raison d'un thread de demande de course longue)
    • Si l'utilisateur quitte la page:
      • La transaction n'est pas annulée - entraînant un traitement inutile, personne ne bénéficiera de
      • L'utilisateur ne peut pas retourner pour voir les résultats après avoir terminé
      • Aucune indication de progression - L'utilisateur attend simplement que la page rafraîchisse

        Il y a plusieurs solutions que j'ai proposées, mais je ne suis pas sûr que je sache, ce qui est meilleur (dans tous les aspects, la performance, la meilleure pratique, l'élégance et la maintenabilité) et j'aimerais savoir quelle est votre solution recommandée et S'il y a une solution que j'ai manquée? (probablement oui, et beaucoup)

        la mauvaise solution : Utilisez le fil de la demande en tant que thread de travailleur, enregistrez l'état de progression dans la session, demandez à un appel AJAX, vérifiez l'état (dans la session) dans une autre demande de paralel

        la solution de compromis : Créez votre propre piscine de thread, gérez un fil de surveillance, un fil de travail et prenez soin de la regroupement en synchronisant les états dans un cache transactionnel distrubué ou un stockage persistant. Cela libère la demande, mais crevette les threads Le serveur d'applications n'est pas au courant et ne fermez pas dans l'interploiement. C'est à vous de fermer les discussions de manière propre et il y a toujours une chance que vous finirez par fuiquer quelque chose. Ce n'est pas la façon J2EE de le faire non plus.

        la solution J2EE : utilisez JMS pour la tâche asynchrone, c'est ce qu'il est de savoir pour

        la solution de printemps : Utilisez le lot de printemps

        Que feriez-vous / faisiez-vous dans vos projets? Quelles autres solutions vous connaissez? Lequel de ceux que j'ai notés ci-dessus est le gagnant de votre avis?


0 commentaires

4 Réponses :


1
votes

La solution que j'ai utilisée avant implique Jetty Cometd au lieu d'Ajax. La principale différence entre Ajax et Cometd est que Cometd peut utiliser davantage d'un pub / sous-modèle - le client (navigateur Web dans ce cas) Subsribe à l'éditeur (votre application) et de l'application pousse les mises à jour et les notifications au navigateur Web comme Apposé à un modèle Ajax d'interrogation constante du serveur par le navigateur Web. Vous pouvez utiliser la solution Cometd même si vous n'utilisez pas de jetée - vous pouvez déposer les pots de jetty dans le dossier LIB de votre serveur Web respectif et que vous devriez être prêt à partir.


0 commentaires

0
votes

Combien de temps fonctionne ces requêtes?

Si vous parlez de sessions expirant, il est peut-être préférable que l'utilisateur ne soit pas attendu pour cela. Il sera toujours gênant que l'utilisateur attendra 20 minutes de pointe de temps en temps dans cette onglet de la requête.

Donc, si des requêtes vraiment longues sont le cas, il est peut-être préférable de changer l'approche d'interface utilisateur et d'avoir l'utilisateur "commander" une requête qu'il revient plus tard à la vue ou est même notifiée par courrier .

Dans un tel cas, je disposerais de la requête préparée dans la DB et la mise en cache, dans une table séparée, là-bas. Signification, je aurai que le serveur Web fonctionne une fois pour enregistrer la demande, disposer d'une tâche DB ou d'un processus / serveur distinct préparez des requêtes sur les demandes et informez-en l'utilisateur, puis auquel le serveur Web l'affiche lorsque l'utilisateur revient pour le Résultats.


2 commentaires

Ceci est couvert par toutes les solutions suggérées, il y aura évidemment un processus de serveur en arrière-plan et une notification à l'utilisateur. La question est la question de la technologie spécifique (la technologie Java à être aussi cuite) est la meilleure pratique à utiliser


@Ehrann: Je suggère que la notification soit "hors ligne" si c'est un très long temps d'attente, et je suggère que cela soit fait dans un travail de DB.



13
votes

Je ferais une combinaison de votre "mauvaise solution" et de la "solution J2EE":

  1. Le fil d'interface utilisateur d'origine envoie un message JMS asynchrone au "Backend" et retourne.
  2. Le backend reçoit la requête asynchrone et le traite.
  3. Lorsqu'un résultat (ou une erreur) est atteint dans le backend, il est renvoyé à la couche de contrôleur.
  4. l'interface utilisateur, qui fait toujours l'interrogation Ajax ou en utilisant Bayeux / Comété, reçoit et affiche le résultat.

    L'astuce consiste à faire correspondre la paire de demandes / de réponse. Je le ferais comme ceci:

    1. créer un "asyncmanagerservice" (AMS) qui a une session, peut-être même une large portée de l'application afin que tous les threads parlent à la même instance.
    2. L'AMS contient une carte avec une identification comme clé et n'importe quel objet comme valeur.
    3. Lors de la création du message JMS de la demande, génère une clé aléatoire unique et placez-la dans le jmscorrélationid du message ainsi que dans la carte, avec null comme valeur. Également passer cet identifiant à l'interface utilisateur.
    4. Laissez le thread de l'UI sondre l'AMS avec l'identifiant précédemment généré aussi longtemps que la valeur de la carte est null . .
    5. Lorsque le résultat est prêt, laissez votre récepteur JMS dans la carte AMS à l'ID donné.
    6. La prochaine fois que le fil de l'interface utilisateur interroge la carte, il recevra la réponse et arrêtera le sondage.

      Ceci est propre et bien résumé de tout domaine concret . Une solution purement technique.

      Même si vous n'aimez pas le sondage, HTTP est apatride à la conception et je pense que ce sondage ne se produit que sur des intervalles bien définis.

      Quoi qu'il en soit, j'ai mis en place un système avec exactement ce modèle et il fonctionne simplement bien ...


0 commentaires

1
votes

Affiche un message à l'utilisateur qui "Votre demande est acceptée et prendra une heure pour être mise à jour"

Vous créez une table qui stocke toutes ces transactions et les processus dans un lot sur le serveur.

L'utilisateur n'aurait pas à attendre longtemps et il sera heureux de voir le message. Vous pouvez envoyer un email de confirmation une fois que votre transaction est traitée.

C'est la meilleure solution que je pense.


0 commentaires