Diese Präsentation wurde erfolgreich gemeldet.
Die SlideShare-Präsentation wird heruntergeladen. ×

Architecture orientée message.pdf

Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Wird geladen in …3
×

Hier ansehen

1 von 49 Anzeige

Weitere Verwandte Inhalte

Ähnlich wie Architecture orientée message.pdf (20)

Aktuellste (20)

Anzeige

Architecture orientée message.pdf

  1. 1. Abdellaziz Walid Département GI a.walid@uiz.ac.ma 2022-2023 MoM : Message Oriented Middleware JMS : Java Messaging Service Architecture Orientée Message MoM : JMS
  2. 2. Contexte asynchrone dans les applications distribués 2 ❑ Parfois un client souhaite envoyer un message sans attendre une réponse de la part de serveur. (communication par message). ❑ Dans ce cas, le client et serveur ne sont pas obligés de partager une interface. ❑ Le serveur n’est pas censé d’être disponible au moment de l’envoi d’un message par un client. ❑ Le serveur n’est pas censé de consommer le message immédiatement. ❑ Les applications client doivent communiquer entre eux de façon asynchrone.
  3. 3. Les limites des middlewares de type RPC 3 ❑ Les (Objet RMI, EJB de type session, service web Soap/Rest) assurent une communication de type RPC seulement (synchrone). ❑ Dans ce type de communication, Un client attend pendant que le serveur effectue le traitement d'une requête. (bloquante) ❑ Couplage fort entre client et serveur (partage la même interface) ❑ Le client doit connaître l’emplacement du serveur (référence). ❑ Dépendance temporelle entre serveur et client. ❑ Pas de diffusion (Unicast seulement). Comment dépasser ces limites ?? Solution : Middleware orienté message (MoM)
  4. 4. Middleware orienté message (MoM) 4 ❑ Proposent un modèle simple et fiable pour l’échange de messages dans une application répartie. ❑ Utilisent un des modèles de communication les plus anciens. ❑ Sont utilisés dans les systèmes de grande dimension ✓ Réseaux bancaires ✓ Télécommunications ✓ Systèmes de réservation, commerce ✓ … etc.
  5. 5. MoM : caractéristiques 5 → Garantie de délivrance de messages → Support des transactions → Gestion du routage → Passage à l’échelle → Support pour la configuration (politiques de QoS) → Composants faiblement couplés - Pas de dépendance d’interface - Pas de référence directe - Pas de dépendance temporelle – l’exécution de l’émetteur n’est pas interrompue si le destinataire n’est pas disponible. - Communication asynchrone / non-bloquante (pas de réponse implicite, sauf ack.)
  6. 6. MoM : Architecture générale 6
  7. 7. MoM : modèles de communication par message 7  Modèle point à point (Point to Point)  Modèle Publication/Abonnement (Publish/Subscribe)
  8. 8. MoM : Modèle point à point 8 ❑ Chaque message est stocké dans une fille (« Queue ») jusqu’à ce que le destinataire le lise ❑ Chaque message est consommé une seule fois (par un seul destinataire) ❑ Pas de dépendance temporelle entre émetteur et destinataire du message ❑ Le destinataire peut acquitter les messages reçus
  9. 9. MoM : Modèle Publication/Abonnement 9 ❑ Sujet (« Topic ») gère l’envoi de messages pour un ensemble de lecteurs abonnés ❑ Découplage entre les « publishers » et les « subscribers » ❑ Les fournisseurs n’ont pas besoins de connaître les consommateurs ❑ Dépendance temporelle ❑ Un client ne peut lire un message qu’après s’être abonné à un topic, ❑ Un client abonné à un topic doit continuer à être actif pour recevoir les message du topic.
  10. 10. MoM : Exemples 10 ❑ Websphere MQ IBM ❑ ActiveMQ ❑ Open MQ ❑ Open JMS ❑ Apache Kafka ❑ Apache Active MQ ❑ RabbitMQ
  11. 11. Java Message Service (JMS) - concepts 11 ❑ JMS : L’implémentation d’un Middleware orienté message (spécifications JMS). ❑ JMS : API standard de Java EE qui assure la communication par message (asynchrone). ❑ Il existe plusieurs implémentations externe de JMS tant commerciales que open source ( Websphere MQ IBM, ActiveMQ, Open MQ,Open JMS…etc) ❑ Les applications utilisent généralement JMS dans les architectures de type B2B (Business to Business). ❑ En effet, cette API permet d'interconnecter n'importe quel système utilisant le principe de messagerie où l'envoi et la réception de message sont asynchrones. ❑ Il permet d’assurer de communications de type unicast, multicast.
  12. 12. Architecture JMS 12
  13. 13. Architecture JMS 13 ❑ Un fournisseur : (Provider) : ❑ C'est l'élément qui a la charge de la livraison des messages entre les différents intervenants. ❑ Il s'occupe de traiter les envois et de faire en sorte qu'ils soient bien reçus. ❑ Il s'agit d'un service qui implémente l'API JMS. ❑ Un client : ❑ C'est une application ou un composant d'application intervenant lors des échanges. ❑ Il envoie ou reçoit les messages. ❑ Un client envoie un message vers une file d'attente, et le client destinataire reste à l'écoute d'une file d'attente pour recevoir le message. ❑ Le transfert du message et sa persistance sont assurés par le fournisseur.
  14. 14. Architecture JMS 14 ❑ Un message : ❑ L'élément qui va transiter via une communication entre les clients. ❑ Un fournisseur sert toujours d'intermédiaire; nous ne les envoyons donc pas directement d'un client à un autre. ❑ Un message est un ensemble de données échangées de manière asynchrone entre les composants. ❑ Il existe plusieurs types de messages (texte, objet, binaire, etc.). ❑ Les destinations : ❑ Ce sont des objets configurés au niveau du fournisseur qui sont à disposition des clients et qui seront utilisés par ces derniers pour l'envoi et la réception des messages. ❑ Pour schématiser, nous pouvons dire qu'il s'agit de boîtes à lettres dans lesquelles sont placées les messages en attendant qu'un client vienne les réclamer. ❑ Ce sont des ressources à rechercher dans l'annuaire JNDI du fournisseur.
  15. 15. Modèles de messagerie 15 JMS offre deux modèles de messagerie : ❑ Le mode point à point utilise les files d'attente (javax.jms.Queue) pour communiquer. ❑ Le mode publication/abonnement utilise des sujets (javax.jsm.Topic) pour échanger des messages. ❑ Chaque mode utilise une interface différente pour envoyer des messages : ▪ javax.jms.QueueSender dans le mode point à point. ▪ javax.jms.TopicPublisher pour le mode publication/abonnement. ❑ Tous les deux héritent de la super interface javax.jms.MessageProducer
  16. 16. Modèle de messagerie : Mode point à point 16 ❑ Chaque message est envoyé par un producteur dans une file d'attente, et est reçu par un seul consommateur. ❑ Une fois le message consommé, il disparaît de la file d'attente.
  17. 17. Modèle de messagerie : Mode publication/abonnement 17 ❑ Un producteur peut envoyer un message à plusieurs consommateurs par le biais d'un sujet (topic). ❑ Chaque consommateur doit cependant être préalablement inscrit à ce sujet sinon il ne reçoit rien. ❑ l'émetteur du message ne connait pas les destinataires qui se sont abonnés. ❑ Il existe deux types de souscription : temporaire et durable. ❑ Dans le cas d'une souscription durable, on oblige le fournisseur à enregistrer les messages lors d'une déconnexion, et à les envoyer lors de la nouvelle connexion du consommateur.
  18. 18. Les composants JMS 18 Il existe un certain nombre de composants qui s'occupe de la gestion globale de JMS, et de permettre ainsi une communication asynchrone entre applications clientes.
  19. 19. Les étapes de création des composants JMS 19
  20. 20. Les étapes de création des composants JMS 1. Localiser le driver JMS ❑ lookup JNDI. Le driver est une connection factory 2. Créer une connection JMS ❑ obtenir une connection à partir de la connection factory 3. Créer une session JMS ❑ Il s'agit d'un objet qui va servir à recevoir et envoyer des messages. On l'obtient à partir de la connection. 4. Localiser la destination JMS ❑ Il s'agit du canal, c'est réglé par le déployeur. On obtient la destination via JNDI. 5. Créer un producteur ou un consommateur JMS ❑ Utilisés pour écrire ou lire un message. On les obtient à partir de la de la session et destination. 6. Envoyer ou recevoir un message
  21. 21. ConnectionFactory et Destination 21 ❑ Pour travailler avec JMS, la première étape consiste d'abord à se connecter au fournisseur JMS. ❑ Pour cela, nous devons récupérer un objet ConnectionFactory via JNDI qui rend ainsi la connexion possible avec le fournisseur. ❑ Cet objet peut être assimilé à une DataSource (en JDBC). ❑ une ConnectionFactory fournit une connexion JMS au service de routage de message. ❑ L'autre élément à récupérer est la destination. ❑ Les destinations (Destination) sont des objets qui véhiculent les messages. ❑ JMS comporte deux types de destination, comme nous venons de le découvrir, les Queue et les Topic.
  22. 22. ConnectionFactory et Destination : exemple 22 Voici le code à proposer côté application cliente (plate-forme indépendante Java SE) : Context ctx = new InitialContext(); ConnectionFactory fabrique = (ConnectionFactory) ctx.lookup("ConnectionFactory"); Destination destination = (Destination) ctx.lookup("queue/MaFile"); Voici une autre code où nous passons par un bean session qui nous permet d'utiliser l'injection. Il suffit alors de spécifier l'annotation @Resource : @Resource(mappedName="ConnectionFactory") private ConnectionFactory fabrique; @Resource(mappedName="queue/MaFile") private Destination destination;
  23. 23. Création du contexte JNDI 23 ❑ Pour obtenir une ConnectionFactory, une Queue, ou un Topic, il faut les rechercher par leur nom dans l'annuaire JNDI ou utiliser l'injection. ❑ Cela suppose donc que ces ressources soient préalablement mis en œuvre et qu'elles soient recensées au travers du service d'annuaire JNDI. ❑ Les propriétés pour la création du contexte JNDI sont dépendantes du fournisseur utilisé jndi.properties (JBoss) # Accès au serveur d'application JBoss java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces java.naming.provider.url=portable:1099
  24. 24. Connection et Session 24 ❑ L'objet ConnectionFactory permet de créer une connexion avec le fournisseur JMS. ❑ Une fois la connexion créée, elle est ensuite utilisée pour créer une session. ❑ La session sert à regrouper toutes les opérations d'envoi et de réception des messages. ❑ Dans la majorité des cas, une session unique est suffisante. ❑ La création de plusieurs sessions est utile seulement dans le cas d'applications multi-tâches qui produisent et reçoivent des messages en même temps. ❑ Effectivement, l'objet Session est mono-tâche, c'est-à-dire que ses méthodes n'autorisent pas l'accès concurrent. ❑ Généralement, le thread qui crée l'objet Session utilise le producteur et le consommateur de cette session.
  25. 25. Connection et Session : exemple 25 Connection connexion = fabrique.createConnection(); Session session = connexion.createSession(true, 0); // createSession(transaction, accuséRéception); ❑ La méthode createSession() prend deux paramètres. ❑ Une session est un contexte transactionnel utilisé pour grouper un ensemble d'envois ou de réceptions de messages dans une même unité de travail. ❑ Si vous désirez travailler avec plusieurs messages pour une même session, vous devez autoriser le mode transactionnel dans le premier argument de la fonction. ❑ Le deuxième argument est utile pour savoir si vous désirez qu'un accusé réception soit renvoyé afin de préciser que message est bien arrivé à sa destination. (AUTO_ACKNOWLEDGE). N.B : N’oublier pas de fermer les connexions une fois le travail terminé. Connection connexion = fabrique.createConnection(); connexion.close();
  26. 26. MessageProducer et MessageConsumer 26 ❑ La dernière étape nous sert à préciser le sens du transfert du message, est-ce pour envoyer ou est-ce pour recevoir ? ❑ Deux objets correspondent à ces deux situations, respectivement MessageProducer et MessageConsumer : //envoi MessageProducer envoi = session.createProducer(destination); envoi.send(message); //réception MessageConsumer reception = session.createConsumer(destination); ………………………….. ❑ Chacune des méthodes de l'objet session prend en paramètre la destination sur laquelle l'objet est connecté.
  27. 27. Composants JMS suivant le mode de communication 27 ❑ ConnectionFactory,Destination,MessageProducer et MessageConsumer sont en réalité des interfaces génériques, que nous pouvons utiliser directement. ❑ Il est toutefois possible, dès le départ, de proposer des interfaces plus spécifiques, qui héritent d'ailleurs de ces interfaces, correspondant respectivement au mode point à point ou au mode publication/abonnement. Générique point à point publication/abonnement ConnectionFactory QueueConnectionFactory TopicConnectionFactory Connection QueueConnection TopicConnection Destination Queue Topic Session QueueSession TopicSession MessageProducer QueueSender TopicPublisher MessageConsumer QueueReceiver TopicSuscriber
  28. 28. Exemple : Queue 28 Context ctx = new InitialContext(); QueueConnectionFactory fabrique = (QueueConnectionFactory) ctx.lookup("QueueConnectionFactory"); Queue destination = (Queue)ctx.lookup("queue/MaFile"); QueueConnection connexion = fabrique.createConnection(); QueueSession session = connexion.createSession(true, 0); QueueSender envoi = session.createProducer(destination); ou QueueReceiver réception= session.createConsumer(destination);
  29. 29. Les messages 29 ❑ Les clients JMS s'échangent des messages, c'est-à-dire qu'un client expédie un message vers une file d'attente, et qu'un client destinataire exécutera un traitement à la réception de ce message. ❑ Dans JMS, un message est un objet Java qui doit implémenter l'interface javax.jms.Message. Il est composé de trois parties : • L'en-tête (header) : qui se compose des informations de destination, d'expiration, de priorité, date d'envoi, etc. • Les propriétés (properties) : qui représentent les caractéristiques fonctionnelles du message. • Le corps du message (body) : qui contient les données à transporter.
  30. 30. Les messages : en-tête 30 Nom Description JMSMessageID identifiant unique de message JMSCorremationID Utilisé pour associer de façon applicative deux messages par leur identifiant. JMSDeliveryMode Il existe deux modes d'envoi : persistant et non persistant (le message peut ne pas être délivré en cas de panne puisqu'il n'est pas rendu persistant). JMSDestination File d'attente destinataire du message. JMSExpiration Date d'expiration du message. JMSPriority Priorité du message. Cet attribut indique la priorité de façon croissante à partir de 0 (les messages de niveau 9 ont plus de priorité que les messages de niveau 0). JMSRedelivered Booléen qui signifie que le message a été redélivré au destinataire. JMSReplyTo File d'attente de réponse du message. JMSTimestamp L'heure d'envoi du message est affecté automatiquement par le fournisseur.
  31. 31. Les messages : Les propriétés 31 ❑ Cette section du message est optionnelle et agit comme une extension des champs d'en-tête. ❑ Les propriétés d'un message JMS sont des couples (nom, valeur), où la valeur est un type de base du langage Java (entiers, chaînes de caractères, booléens, etc.). ❑ L'interface javax.jms.Message définit des accesseurs pour manipuler ces valeurs. Ces données sont généralement positionnées par le client avant l'envoi d'un message.
  32. 32. Les messages : le corps 32 Interface Description javax.jms.BytesMessage Pour les messages sous forme de flux d'octets. javax.jms.TextMessage Echange de données de type texte. javax.jms.ObjectMessage Messages composés d'objets Java sérialisés. javax.jms.MapMessage Echange de données sous la forme clé/valeur. La clé doit être une String et la valeur de type primitif. javax.jms.StreamMessage Echange de données en provenance d'un flux. ❑ Le corps du message contient les données. ❑ Ces données sont formatées selon le type du message qui est défini par les interfaces suivantes (qui héritent toutes de javax.jms.Message) :
  33. 33. Exemple 33 Session session = connexion.createSession(true, 0); MessageProducer envoi= session.createProducer(destination); BytesMessage message = session.createBytesMessage(); message.writeInt(15); message.writeDouble(-6.78); message.writeBoolean(true); envoi.send(message); ////////////////////////////////////////////////////////////////////////////////////////////////// Session session = connexion.createSession(true, 0); MessageProducer envoi = session.createProducer(destination); TextMessage message = session.createTextMessage(); message.setText("Bienvenue"); envoi.send(message);
  34. 34. Exemple : Envoyer un objet 34 class Personne implements Serializable { ... } //////////////////////////////////////////////////////////////////////////////////////// Personne moi = new Personne(); Session session = connexion.createSession(true, 0); MessageProducer envoi = session.createProducer(destination); ObjectMessage message = session.createObjectMessage(); message.setObject(moi); envoi.send(message);
  35. 35. Comment envoyer un message ? 35 ❑ Tout d'abord, la fabrique de connexion (ConnectionFactory) et la destination (Destination) doivent être connues par le client JMS. ❑ Une fois la référence de la ConnectionFactory obtenue, on se connecte au provider (fournisseur) JMS via l'objet Connection. ❑ A partir de cette connexion, nous devons obtenir une session (Session). ❑ A partir de cette session, nous devons créer un MessageProducer qui va permettre d'envoyer des messages auprès d'une destination. ❑ La session permet également de créer le message suivant le type choisi.
  36. 36. Exemple 36 Context ctx = new InitialContext(); ConnectionFactory fabrique = (ConnectionFactory)ctx.lookup("ConnectionFactory"); Destination destination = (Destination)ctx.lookup("queue/MaFile"); Connection connexion = fabrique.createConnection(); Session session = connexion.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer envoi = session.createProducer(destination); TextMessage message = session.createTextMessage(); message.setText("Bienvenue"); message.setText(" à tout le monde"); envoi.send(message); connexion.close();
  37. 37. Comment recevoir un message ? 37 ❑ Comme l'envoi d'un message, la fabrique de connexion (ConnectionFactory) et la destination (Destination) doivent être connues par le client JMS. ❑ Une fois la référence de la ConnectionFactory obtenue, le consommateur doit se connecter au provider (fournisseur) JMS via l'objet Connection. ❑ A partir de cette connexion, nous devons obtenir une session (Session). ❑ A partir de la session, on crée un MessageConsumer qui va permettre de consommer les messages. ❑ Pour ce faire, nous associons un listener MessageListener pour traiter les messages de façon asynchrone. Ainsi, à chaque réception d'un nouveau message, la méthode onMessage() est automatiquement invoquée et peut effectuer le traitement désiré. N.B : Il ne faut surtout pas oublier de démarrer la connexion avec la méthode start() sinon aucun message ne sera reçu.
  38. 38. Exemple 38 class Réception implements MessageListener { public Réception() throws Exception { Context ctx = new InitialContext(); ConnectionFactory fournisseur = (ConnectionFactory) ctx.lookup("ConnectionFactory"); Destination destination = (Destination)ctx.lookup("queue/maFile"); Connection connexion = fournisseur.createConnection(); Session session = connexion.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageConsumer réception = session.createConsumer(destination); réception.setMessageListener(this); connexion.start(); }
  39. 39. Exemple (Suite) 39 public static void main(String[] args) throws Exception { new Réception(); } public void onMessage(Message arg) { try { TextMessage message = (TextMessage) arg; System.out.println(message.getText()); System.out.println(message.getText()); } catch (Exception ex) { } } }
  40. 40. Problématique Dans le cas de l’exécution d’une méthode métier à l’écoute d’un nouveau message (ex: modification de la base de données, envoi d’email, fax ou autres), il serait nécessaire de coder une application à l’écoute des messages, qui délègue ensuite le traitement métier à un EJB de type session bean. ❑ Cette solution est difficile à développer, peu fiable, car l’application intermédiaire ajoute un niveau architecturel ❑ Susceptible de tomber en panne. Il est donc nécessaire de réaliser l’écoute JMS directement au niveau de l’EJB métier. ❑ Ce mécanisme utilisant un EJB serait également envisageable, mais un EJB est conçu pour répondre à des sollicitations externes, non pour être à l’écoute d’évènements.
  41. 41. Solution : Message-Driven Bean MDB consomme des messages depuis les queues ou topics, envoyés par les clients JMS.
  42. 42. Qu'est-ce qu'un Message-Driven Bean ? ❑ Un client n'accède pas à un MDB via une interface, il utilise l'API JMS. ❑ Un MDB n'a pas d'interface. ❑ Les MDB possèdent une seule méthode, faiblement typée : onMessage() - Elle accepte un message JMS (BytesMessage, ObjectMessage, TextMessage, StreamMessage ou MapMessage) ❑ Les MDB n'ont pas de valeur de retour, ils sont découplés des producteurs de messages.
  43. 43. Qu'est-ce qu'un Message-Driven Bean ? ❑ Les MDB ne renvoient pas d'exceptions au client (mais au contenueur EJB) ❑ Les MDB sont stateless. ❑ Les MDB peuvent être des abonnés durables ou non-durables à un topic. (par défaut non durable) ❑ Annotation pour les rendre durable : @ActivationConfigProperty(propertyName="subscriptionDurability", propertyValue="Durable") })
  44. 44. Cycle de vie d’un MDB 44
  45. 45. Développer un Message-Driven Bean 1) Nous devons en premier lieu utiliser l'annotation @MessageDriven et spécifier le paramètre mappedName dont la valeur correspond à la destination du service JMS. 2) Une fois que vous avez réalisé cette opération, vous pouvez choisir le nom de votre classe. 3) Il faut que le MDB implémente l'interface MessageListener et redéfinisse donc la méthode associée onMessage() qui sera donc automatiquement sollicité à chaque arrivée d'un nouveau message. 4) Remarquez qu'avec les MDB, vous n'avez plus à vous préoccuper des objets annexes comme Connection, Session, MessageConsumer. Tout se fait automatiquement en tâche de fond. 5) Comme tous les autres beans, le MDB possède des méthodes callback interceptor qui sont appelées respectivement à la suite de la construction de l'objet et juste avant sa destruction. Ces méthodes possèdent alors les annotations suivantes : @PostConstruct et @PreDestroy.
  46. 46. Exemple : La classe du bean
  47. 47. La classe du bean (suite)
  48. 48. Le client import javax.naming.*; import javax.jms.*; import java.util.*; public class Client { public static void main(String[] args) throws Exception{ // Initialize JNDI Context ctx = new InitialContext(System.getProperties()); // 1: Lookup ConnectionFactory via JNDI TopicConnectionFactory factory = (TopicConnectionFactory) ctx.lookup("javax.jms.TopicConnectionFactory"); // 2: Create JMS connection TopicConnection connection =factory.createTopicConnection();
  49. 49. Le client (suite) // 3: Use Connection to create session TopicSession session = connection.createTopicSession( false, Session.AUTO_ACKNOWLEDGE); // 4: Lookup Destination (topic) via JNDI Topic topic = (Topic) ctx.lookup("testtopic"); // 5: Create a Message Producer TopicPublisher publisher =session.createPublisher(topic); // 6: Create a text message, and publish it TextMessage msg = session.createTextMessage(); msg.setText("This is a test message."); publisher.publish(msg); } }

×