web-dev-qa-db-fra.com

Relation entre les connexions JMS, les sessions et les producteurs / consommateurs

Je veux envoyer un lot de 20 000 messages JMS vers une même file d'attente. Je divise la tâche en utilisant 10 threads, donc chacun traitera 2k messages. Je n'ai pas besoin de transactions.

Je me demandais si avoir une connexion, une session et 10 producteurs est la voie recommandée ou non?

Et si j'avais un producteur partagé par tous les fils? Mes messages seraient-ils corrompus ou seraient-ils envoyés synchronisés (sans gain de performances)?

Quelle est la ligne directrice générale pour décider de créer une nouvelle connexion ou session si je me connecte toujours à la même file d'attente?

Merci et désolé d'avoir demandé beaucoup à la fois.

(Voici une question similaire, mais elle ne répond pas tout à fait à ce que je cherchais. Les sessions JMS de longue durée. Garder les connexions JMS/sessions JMS ouvre-t-il toujours une mauvaise pratique? )

42
Russell

Est-ce OK si certains des messages sont dupliqués ou perdus? Lorsque le client JMS se connecte au courtier JMS sur le réseau, tout appel API se déroule en trois phases.

  1. L'appel d'API, y compris les données de message, est transmis par câble au courtier.
  2. L'appel d'API est exécuté par le courtier.
  3. Le code de résultat et toutes les données de message sont retransmis au client.

Considérez le producteur pendant une minute. Si la connexion est rompue à la première étape, le courtier n'a jamais reçu le message et l'application devrait le renvoyer. Si la connexion est rompue à la troisième étape, le message a été envoyé avec succès et le renvoyer produirait un message en double. L'application ne peut pas faire la différence entre eux et le seul choix sûr est donc de renvoyer le message en cas d'erreur. Si la session est effectuée, le message peut être renvoyé en toute sécurité dans tous les cas, car si l'original était parvenu au courtier, il sera annulé.

Considérez le consommateur. Si la connexion est perdue à la troisième étape, le message est supprimé de la file d'attente mais n'est jamais retourné au client. Mais si la session est effectuée, le message sera rediffusé lorsque l'application se reconnectera.

En dehors des transactions, il y a la possibilité de messages perdus ou en double. À l'intérieur d'une transaction, la même fenêtre d'ambiguïté existe mais elle se trouve sur l'appel COMMIT plutôt que sur PUT ou GET. Avec les sessions traitées, il est possible d'envoyer ou de recevoir un message deux fois mais pas d'en perdre un.

La spécification JMS reconnaît cette fenêtre d'ambiguïté et fournit les conseils suivants:

Si un échec se produit entre le moment où un client valide son travail sur une session et la méthode de validation retourne, le client ne peut pas déterminer si la transaction a été validée ou annulée. La même ambiguïté existe en cas d'échec entre l'envoi non transactionnel d'un message PERSISTENT et le retour de la méthode d'envoi.

Il appartient à une application JMS de gérer cette ambiguïté. Dans certains cas, cela peut amener un client à produire des messages fonctionnellement en double.

Un message qui est redistribué en raison de la récupération de session n'est pas considéré comme un message en double.

Les sessions JMS doivent toujours être traitées, sauf dans les cas où il est vraiment OK de perdre des messages. Si les sessions sont traitées, vous aurez besoin d'une session et d'une connexion par thread en raison du modèle de thread JMS.

Tout conseil concernant les impacts sur les performances serait spécifique au fournisseur, mais en général, les messages persistants en dehors du point de synchronisation sont renforcés sur le disque avant le retour de l'appel d'API. Mais un appel traité peut retourner avant que le message persistant ne soit écrit sur le disque tant que le message persiste avant le retour de COMMIT. Si le fournisseur optimise en fonction de cela, il est beaucoup plus performant d'écrire plusieurs messages sur le disque, puis de les valider par lots. Cela permet au courtier d'optimiser les écritures et les vidages de disque par bloc de disque plutôt que par message. Le nombre de messages à mettre dans la transaction diminue avec la taille du message et au-delà d'une certaine taille de message diminue à un.

Si vos 20 000 messages sont relativement petits (mesurés en k et non en Mo), vous souhaiterez probablement utiliser des sessions traitées par thread et régler l'intervalle de validation.

28
T.Rob

Dans la plupart des scénarios, il suffit de travailler avec une connexion et plusieurs sessions, en utilisant une session par thread. Dans certains environnements, vous pouvez gagner des performances supplémentaires en utilisant plusieurs connexions:

Certains systèmes de messagerie prennent en charge un mode cluster, où les connexions sont équilibrées en charge vers différents nœuds. Avec plusieurs connexions, vous pouvez utiliser les performances de plusieurs nœuds dans ce scénario. (ce qui bien sûr n'aide que lorsque le goulot d'étranglement est du côté du courtier de messages).

La meilleure solution serait de nous un pool de connexions, et de donner à l'administrateur quelques options pour configurer le comportement dans la zone spécifique.

9
roundrobin
I was wondering if having one connection, one session, and 10 producers
is the recommended way to go or not? 

Bien sûr, mais le point à noter ici est que vous utilisez un seul thread, c'est-à-dire celui que vous créez lors de la création de l'objet Session. Les 10 producteurs sont liés à cet objet de session et par conséquent au même fil.

How about if I had one producer shared by all the threads? Would my messages
be corrupt or would it be sent out synchronized (giving no performance gain)?

Très mauvaise idée je dirais. Les spécifications JMS indiquent clairement que la session ne doit pas être partagée par plus d'un thread. Ce n'est pas sûr pour les threads.

What's the general guideline of deciding whether to create a new connection
or session if I'm always connecting to the same queue?

Si votre système prend en charge le multithreading, vous pouvez créer plusieurs sessions (chaque session correspond à un seul thread) à partir d'une seule connexion. Chaque session peut avoir plusieurs producteurs/consommateurs mais tous ceux-ci ne doivent pas être partagés entre les threads.

4
Aniket Thakur

D'après ce que j'enquête sur ce sujet, une session signifie un fil. Ceci est basé sur les spécifications JMS. Si vous voulez le filetage multiple (plusieurs producteurs/consommateurs), plusieurs sessions doivent être créées, une connexion est très bien.

4
Cystal

En théorie, les connexions sont thread-safe mais toutes les autres ne le sont pas, vous devez donc créer une session par thread.

En réalité, cela dépend de l'implémentation JMS que vous utilisez.

1
Claude Vedovini