Est-ce une bonne pratique à utiliser JMS File d'attente Temporaire synchrone utiliser?
Si nous utilisons JMS demande/réponse mécanisme à l'aide "File d'attente Temporaire", ce que ce code est-il évolutif?
Comme de maintenant, nous ne savons pas si nous allons soutenir les 100 requêtes par seconde, ou 1000s de requêtes par seconde.
Le code ci-dessous est ce que je pense de la mise en œuvre. Il rend l'utilisation de JMS dans un "Synchrone" de la mode. Les éléments clés sont où le "Consommateur" est créé au point une "File d'attente Temporaire" qui a été créé pour cette session. J'ai juste ne peux pas savoir si l'aide de ces Files d'attente Temporaires est une conception évolutive.
destination = session.createQueue("queue:///Q1");
producer = session.createProducer(destination);
tempDestination = session.createTemporaryQueue();
consumer = session.createConsumer(tempDestination);
long uniqueNumber = System.currentTimeMillis() % 1000;
TextMessage message = session
.createTextMessage("SimpleRequestor: Your lucky number today is " + uniqueNumber);
//Set the JMSReplyTo
message.setJMSReplyTo(tempDestination);
//Start the connection
connection.start();
//And, send the request
producer.send(message);
System.out.println("Sent message:\n" + message);
//Now, receive the reply
Message receivedMessage = consumer.receive(15000); //in ms or 15 seconds
System.out.println("\nReceived message:\n" + receivedMessage);
Mise à jour:
Je suis tombé sur un autre modèle, voir ce blog
L'idée est d'utiliser des "normaux", les Files d'attente pour Envoyer et Recevoir des. Cependant, pour 'Synchrone' appels, afin d'obtenir la Réponse désirée (c'est à dire correspondant à la demande), vous créez un Consommateur à l'écoute de la file d'attente de réception à l'aide d'un Sélecteur'.
Suit:
//1. Create Send and Receive Queue.
//2. Create a msg with a specific ID
final String correlationId = UUID.randomUUID().toString();
final TextMessage textMessage = session.createTextMessage( msg );
textMessage.setJMSCorrelationID( correlationId );
//3. Start a consumer that receives using a 'Selector'.
consumer = session.createConsumer( replyQueue, "JMSCorrelationID = '" + correlationId + "'" );
De sorte que la différence de ce modèle est que nous ne créons pas une nouvelle temp File d'attente pour chaque nouvelle demande.
Au lieu de toutes les réponses viennent à une seule file d'attente, mais l'utilisation d'un sélecteur " pour que chaque demande-thread reçoit seulement la réponse se soucie.
Je pense que l'inconvénient ici est que vous devez utiliser un sélecteur'. Je ne sais pas encore si c'est moins privilégiées ou plus par défaut que mentionné plus tôt motif. Pensées?
- Ce mécanisme a été proposé dans une Question précédente que j'avais demandé: stackoverflow.com/q/10778485/233306 j'ai créé cette nouvelle Question juste pour savoir si c'est une conception évolutive
- Bonjour, pourriez-vous s'il vous plaît de partager la méthode qui vous avez finalement décidé de l'utiliser? Ne l'une des 2 méthodes de tempq/sélecteur a importants performance/scallability des avantages sur les autres? Merci.
Vous devez vous connecter pour publier un commentaire.
Concernant la mise à jour dans votre post - sélecteurs sont très efficace si elle est effectuée sur les en-têtes de message, comme vous êtes en train de faire avec l'ID de Corrélation. Spring Integration aussi à l'intérieur le fait pour la mise en œuvre de JMS Sortant de la passerelle.
jmsRequest.setJMSCorrelationID(correlationId); messageSelector = "JMSCorrelationID = '" + correlationId + "'";
Fait intéressant, l'évolutivité de cette peut-être en fait le contraire de ce que les autres réponses ont décrit.
WebSphere MQ enregistre et réutilise dynamique de la file d'attente des objets lorsque cela est possible. Donc, bien que l'utilisation d'une dynamique de la file d'attente n'est pas libre, il n'est bien parce que les files d'attente sont libérés, tout ce qui WMQ besoin de faire est de passer la poignée pour le prochain thread qui demande une nouvelle file d'attente de l'instance. Dans une longue QMgr, le nombre de dynamique des files d'attente restera relativement statique, tandis que les poignées sont passés de filet. Strictement parlant, il n'est pas aussi rapide que la réutilisation d'une seule file d'attente, mais il n'est pas mauvais.
D'autre part, même si l'indexation sur
CORRELID
est rapide, la performance est l'inverse pour le nombre de messages dans l'index. Il a également fait une différence si la profondeur de file d'attente commence à se construire. Lorsque l'application va unGET
avecWAIT
sur une zone vide de la file d'attente il n'y a pas de retard. Mais sur une profondeur de file d'attente, le QMgr est à rechercher dans l'index des messages existants pour déterminer que le message de réponse n'est pas parmi eux. Dans votre exemple, c'est la différence entre la recherche dans un index vide par rapport à un grand indice de 1 000 s de fois par seconde.Le résultat est que 1000 dynamique des files d'attente avec un message à chaque peut effectivement être plus rapide qu'une seule file d'attente avec 1000 threads arriver par
CORRELID
, selon les caractéristiques de l'application et de la charge. Je recommande de tester ce à l'échelle avant de s'engager à un design particulier.À l'aide de sélecteur d'ID de corrélation sur une file d'attente partagée à l'échelle de très bien avec plusieurs consommateurs.
1000 requêtes /s sera cependant beaucoup. Vous pouvez diviser la charge un peu entre les différentes instances si la performance s'avère être un problème.
Vous pourriez voulez des précisions sur les demandes de vs clients numéros. Si le nombre de clients qui sont < 10 et restera plutôt statique, et le numéro de la demande sont très élevés, les plus résistants et rapide solution pourrait être d'avoir statique répondre files d'attente pour chaque client.
La création de files d'attente temporaires n'est pas gratuit. Après tout, c'est l'allocation des ressources sur le courtier(s). Cela dit, si vous avez un inconnu (avant de la main) potentiellement indépendant du nombre de clients (plusieurs machines virtuelles, plusieurs threads simultanés par la JVM, etc) vous ne pouvez pas avoir un choix. Par l'allocation de client files d'attente et de les affecter aux clients de sortir de la main rapide.
Certainement ce que vous avez esquissé est la plus simple solution possible. Et si vous pouvez obtenir des nombres réels pour un volume de transactions, et s'adapte assez bien.
Avant que je le regarde en évitant les files d'attente temporaires, j'aurais l'air plus à limiter le nombre de clients et de rendre les clients de longue durée. C'est-à-dire créer un pool de client sur le côté client, et ont les clients dans la piscine créer la file d'attente temporaire, session de connexion, etc. au démarrage, de les réutiliser sur les demandes ultérieures, et la larme à l'arrêt. Ensuite, le réglage d'un problème devenu l'un des max/min de la taille de la piscine, ce que le temps d'inactivité est de nettoyer la piscine, et ce que le comportement est (échec vs bloquer) lorsque la piscine est au maximum. Sauf si vous êtes en train de créer un nombre arbitrairement grand de transitoire de la Jvm (dans ce cas, vous avez plus des questions d'échelle juste à partir de la JVM de démarrage de frais généraux), qui devrait échelle ainsi que quoi que ce soit. Après tout, au point que les ressources que vous allouez de refléter l'utilisation réelle du système. Il n'y a vraiment pas de possibilité d'utiliser moins.
La chose à éviter est de la création et de la destruction d'un grand gratuite nombre de de files d'attente, les sessions, les connexions, etc. La conception du serveur, afin d'autoriser la diffusion de l'aller. Puis la piscine si/quand vous en avez besoin. Comme pas, pour rien, non négligeable, vous aurez besoin d'.
session.createTemporaryQueue();
Et depuis les Sessions ne peuvent pas être mis en commun, je ne sais pas si la mise en commun des Sessions peuvent être utilisés.L'aide temporaire d'attente aura un coût créer relyToProducers chaque à chaque fois. Au lieu d'utiliser le cache des producteurs pour une charge statique replyToQueue, la méthode createProducer sera plus coûteux et impact sur les performances dans un très simultanées invocation de l'environnement.
J'ai été confrontée au même problème et a décidé de pool de connexions de moi-même à l'intérieur d'un stateless bean. Un client de connexion a un tempQueue et la pose à l'intérieur de JMSMessageExchanger objet (qui contient connectionFactory,la File d'attente et tempQueue), qui est de se lier à une instance de bean. J'ai testé dans la JSE/EE environnements. Mais je ne suis pas vraiment sûr de Glassfish JMS piscine comportement.
Il fait fermer les connexions JMS, obtenu "à la main" après bean méthode se termine?Suis-je en train de faire quelque chose de mal?
Également Ive éteint transaction client bean (TransactionAttributeType.NOT_SUPPORTED) pour envoyer des messages de demande immédiatement à la demande de la file d'attente.
La même classe est utilisé dans le client (stateless bean) et le serveur (@MessageDriven).
RequestProducer et ResponseProducer sont des interfaces:
Aussi j'ai lu AMQ article sur requête-réponse en œuvre au cours de AMQ:
http://activemq.apache.org/how-should-i-implement-request-response-with-jms.html
Je suis peut-être trop tard, mais j'ai passé quelques heures cette semaine pour obtenir une Demande de synchronisation/Répondre travaillant au sein de JMS. Ce sujet de l'extension de la QueueRequester avec délai d'attente. Je l'ai fait et au moins les tests sur une seule machine (l'exécution de courtier, demandeur et le répondant) a montré que cette solution est plus performante que la discuté ceux. De l'autre côté, il dépend de l'aide d'un QueueConnection et cela signifie que vous pouvez être obligé d'ouvrir plusieurs Connexions.