1 / 65

Üzenetkezelés

Üzenetkezelés. Tartalom. C élok RPC modell MOM modell JMS MSMQ Web-szolgáltatások és az üzenetkezelés. C élok. RPC problémáinak bemutatása Üzenetkezelő rendszerek működésének megértése A legfontosabb üzenetkezelő API-k megismerése Előnyök és hátrányok

Télécharger la présentation

Üzenetkezelés

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Üzenetkezelés

  2. Tartalom • Célok • RPC modell • MOM modell • JMS • MSMQ • Web-szolgáltatásokés az üzenetkezelés

  3. Célok • RPC problémáinak bemutatása • Üzenetkezelő rendszerek működésének megértése • A legfontosabb üzenetkezelő API-k megismerése • Előnyök és hátrányok • RPC, MOM és web-szolgáltatások viszonyának megértése: • mikor melyiket érdemes használni

  4. RPC modell • RPC, CORBA és bizonyos értelemben a WS over HTTP is ilyenek int Add(int left, int right) compiler int Add(int left, int right) { return left+right; } int result = Add(5,8); Kérés: Add Paraméterek: 5, 8 Add skeleton Add stub Válasz: 13

  5. Problémák • A modell nem oldja meg a következő problémákat: • A hálózati kapcsolat megszakad, kihagyások vannak (pl. WLAN) • Üzemszünet a kiszolgáló oldalán • Burst jellegű kérések (pl. adóbevallás) • Skálázás • Prioritások • Tranzakciók • Változtatás, fejlődés

  6. Az RPC problémái • Egyszerű kommunikáció, amelynek ára van: • kérés/válasz kommunikáció: • minden kérésre választ várunk • a kliens blokkolódik a válasz megérkezéséig • a szervernek mindig elérhetőnek kell lennie • a servant-ok és stub-ok fordítási időben fixálódnak • az erős típusosság megkönnyíti a programozást • de a változtatás nehezebb • az RPC alapja a viselkedés

  7. Megoldás: üzenetkezelés • Szedjük szét az RPC-t: • RPC = kérés üzenet + válasz üzenet • kezeljük külön a kettőt • különböző MEP-ek (Message Exchange Pattern): • request-response, one-way (fire-and-forget), solicit-notify, request-async response • Az üzenetkezelés alapja az adat • üzenetből indulunk ki, nem contract-ból • a contract-ot igazítjuk az üzenethez • megjegyzés: kicsit hasonlít az RPC-hez • pl. UjUgyfel típusú üzenet hatására létrehozunk egy új ügyfelet • probléma: állapottal rendelkező kapcsolat

  8. Mi az üzenetkezelés? • Üzenet: fejlécek + tartalom • az átvitel lehet aszinkron • a tartalom formátuma nincs megkötve • Cél végpont: névkatalógus alapján • szétcsatolja a producer-t és a consumer-t • az üzenetek átirányítása, route-olása egyszerűbb • Futtató környezet: különböző átviteli módszerek • megbízható, tranzakciós, prioritásos, határidős, publish-subscribe • egy vagy több csatornát biztosít a továbbításra

  9. Üzenetkezelő-rendszer példák

  10. MOM • MOM = Message Oriented Middleware • Előnyök: • flexibilitás • többfajta MEP (one-way, multicast, disconnected, ...) • üzenetek transzformációja, route-olása • könnyebb karbantartás, változtatás (az üzenet formátuma változhat: nem kell minden klienst újrafordítani) • dead-lock elkerülése (ld. RPC blokkolódás) • burst terhelés kezelése • a queue-k tárolják az üzeneteket • a feldolgozók olyan gyorsan dolgozhatnak, ahogy szeretnének • újabb feldolgozók hozzáadhatók vagy megvárható, amíg a terhelés alábbhagy • integráció • az üzenet maga a típus • nem szükséges szorosan csatolt API • különböző rendszerek között is jó (pl. XML a .NET és Java között) • üzenetek transzformációja, route-olása

  11. Üzenetkezelő-rendszer problémák • A kommunikáció egy queue-val történik, nem egy objektummal • kétirányú kommunikáció legalább két queue-t igényel • Nincs állapot • az üzenetek sorrendje nem garantált • szinkron kommunikáció emulálása plusz munkát igényel • Az objektumok nem azonosíthatók • az üzenetek egy queue-ba érkeznek, nem egy objektumhoz • nem hagyományos kliens-szerver • inkább termelő-fogyasztó jellegű • Kérés-válasz típusú kommunikáció esetén maradjunk az RPC modellnél! • Megjegyzés: a web-szolgáltatások transzportrétegtől függően támogatják mindkét modellt (ld. később)

  12. JMS: Java Messaging System

  13. JMS: Java Messaging System • Üzenetkezelés kliens oldali interfészét specifikálja Java-ban • verziók: 1.0.2b, 1.1 • package: javax.jms.* • Támogatja a legfontosabb üzenetkezelési feladatokat: • szinkron és aszinkron működés • lazán- és erősen csatolt műveletek • point-to-point és publish-subscribe • garantált vagy gyors átvitel • tranzakciós küldés/fogadás • prioritások • határidők • szűrés

  14. JMS queue modell • point-to-point sender receiver queue receiver message message message receiver sender

  15. JMS topic modell durable subscriber (attached) • publish-subscribe transient subscriber (attached) publisher topic message message message transient subscriber (attached) publisher durable subscriber (detached) ismételt csatlakozáskor

  16. Programozási modell • Mindkét modellre hasonló: • Factory: JNDI alapján kikeresve • Connection: fizikai kapcsolat a JMS provider-hez • Session: szál szintű környezet küldéshez és fogadáshoz • Destination: a végpont, JNDI alapján kinyerhető • A Factory és a Destination ún. adminisztrált objektumok (Administered Object) • felvételük: rendszeradminisztrátorok által, nem programozók által • néhány JMS provider biztosít ehhez API-t is

  17. Programozási modell Connection Factory létrehozza Connection Message Producer előállít létrehozza ráépül létrehozza Session Destination Message szinkron feldolgozás (pollozás) aszinkron feldolgozás (callback) ráépül létrehozza Message Consumer Message Listener aszinkron feldolgozás (callback)

  18. Programozási modell

  19. Connection létrehozása • ConnectionFactory kikeresése • Connection létrehozása • A start()-ot utoljára hívjuk meg! • Általában egy Connection példány egy JVM-ben elég // A nevet a rendszeradminisztrátor választja: String qfname = "jms/MyQueueConnectionFactory"; Context ctx = newInitialContext(); QueueConnectionFactory qfac = (QueueConnectionFactory)ctx.lookup(qfname); QueueConnection qcon = qfac.createQueueConnection(); // ...egyéb beállítások... qcon.start(); // üzenetek fogadásának kezdete

  20. Session létesítése • Létrehozás a Connection segítségével • Csak az adott szálra biztonságos! • Opciók: • tranzakció (JTA) • visszaigazolás típusa • AUTO_ACKNOWLEDGE • CLIENT_ACKNOWLEDGE • DUPS_OK_ACKNOWLEDGE QueueConnection qcon = ...; // korábbról QueueSession qsession = qcon.createQueueSession( false, // tranzakció? Session.AUTO_ACKNOWLEDGE); // visszaigazolás módja

  21. Visszaigazolás típusa • AUTO_ACKNOWLEDGE • Minden egyes üzenet automatikusan visszaigazolásra kerül. A Session szál blokkolódik, amíg a broker feldolgozza a visszaigazolást. • CLIENT_ACKNOWLEDGE • A kliens explicit igazolja vissza az üzeneteket az üzenet acknowledge() függvényével. Minden eddig átvett üzenet visszaigazolódik. A Session szál blokkolódik, amíg a broker feldolgozza a visszaigazolást. • DUPS_OK_ACKNOWLEDGE • A Session 10 üzenet után igazol vissza, a szál nem blokkolódik. Üzenet nem veszik el, de lehetséges, hogy többször is kézbesítődik.

  22. Destination kikeresése • JNDI alapján • A nevet az adminisztrátor állítja be • Tipikus prefix: „jms/” (de nem kötelező) Context ctx = ...;// korábbról // A nevet a rendszeradminisztrátor választja: String qname = "jms/MyQueue"; Queue queue = (Queue)ctx.lookup(qname);

  23. Producer létrehozása • Ahhoz a Session-höz kötődik, amelyik létrehozta • Ez küldi az üzeneteket QueueSession qsession = ...; // korábbról Queue queue = ...; // korábbról QueueSender qsender = qsession.createSender(queue);

  24. Message felépítése • Három rész: • headers: fejlécek a JMS számára route-oláshoz • properties: tulajdonságok az alkalmazás számára • body: az üzenet törzse, a tényleges adat

  25. Üzenet fejlécei

  26. Üzenet tartalma • A Session hozza létre az üzenetet • Fajtái: • StreamMessage: a tartalom DataOutputStream-ként jelenik meg, feltölthető Java primitívekkel • MapMessage: rendezetlen név-érték párok • TextMessage: Java String, pl. egy XML • ObjectMessage: sorosított Java objektum • BytesMessage: byte-tömb • Message: nincs törzs, csak fejlécek és property-k

  27. Üzenetek előállítása StreamMessage sm = qsession.createStreamMessage(); sm.writeString("foo"); sm.writeInt(7); sm.writeDouble(2.5); MapMessage mm = qsession.createMapMessage(); mm.setInt("num1", 7); mm.setString("name", "foo"); mm.setDouble("num2", 2.5); TextMessage tm = qsession.createTextMessage(); tm.setText("hello"); ObjectMessage om = qsession.createObjectMessage(); MyObject obj = newMyObject("foo", 7, 2.5); om.setObject(obj); BytesMessage bm = qsession.createBytesMessage(); byte[] data = newbyte[3]; bm.writeBytes(data); Message m = qsession.createMessage();

  28. Üzenet elküldése • A Producer küldi el • A fejlécek felülbírálhatók: • deliveryMode: perzisztens-e • PERSISTENT: megbízható, pontosan egyszeri továbbítás, lassabb • NON_PERSISTENT: nem megbízható (üzenetek elveszhetnek), legfeljebb egyszeri továbbítás, gyorsabb • priority: prioritás (0 – alacsony, ..., 9 – magas) • timeToLive: élettartam milliszekundumokban (ha 0, akkor nem jár le) Message msg = ...; // korábbról QueueSender qsender = ...; // korábbról qsender.send(msg); int priority = 0; long timeToLive=0; qsender.send(msg, DeliveryMode.PERSISTENT, priority, timetolive); int priority = 9; long timeToLive=10*1000; qsender.send(msg, DeliveryMode.NON_PERSISTENT, priority, timetolive);

  29. Consumer létrehozása • A Session hozza létre • A Session-höz és a Destination-höz kötődik QueueSession qsession = ...; // korábbról Queue queue = ...; // korábbról QueueReceiver qreceiver = qsession.createReceiver(queue);

  30. Üzenet fogadása (szinkron) • pollozás a receive() függvénnyel: • blokkol • paraméterként megadható a time-out milliszekundumokban • pollozás a receiveNoWait() függvénnyel: • nem blokkol, azonnal visszatér • ha nincs üzenet null a visszatérési érték • visszatérési érték típusa: Message • igény esetén cast-olni kell

  31. Üzenet fogadása (szinkron) while (true) { Message m = qreceiver.receive(); if (m instanceofBytesMessage) { BytesMessage bm = (BytesMessage)m; byte data []; int len = bm.readBytes(data); } elseif (m instanceofTextMessage) { TextMessage tm = (TextMessage)m; StringBuffer sb = tm.getText(); } elseif (m instanceofObjectMessage) { ObjectMessage om = (ObjectMessage)m; MyObject obj = (MyObject)om.getObject(); String s = obj.getFoo(); int i = obj.getNum(); } }

  32. Üzenet fogadása (aszinkron) • Regisztrálni kell egy MessageListener interfészt implementáló osztályt a Consumer-nél • Minden onMessage() hívás külön szálon fut!

  33. Üzenet fogadása (aszinkron) classMyListenerimplementsMessageListener { publicvoid onMessage(Message m) { try { if (m instanceofStreamMessage) { //... } elseif (m instanceofMapMessage) { //... } } catch (Throwable t) { // Hiba a feldolgozás során } } } //... qreceiver.setMessageListener(newMyListener());

  34. Üzenetek szűrése • Egy selector segítségével szűrhetők a beérkező üzenetek • A feltételek a header és a property fejlécekre vonatkozhatnak • Nyelv: SQL-92 egy részhalmaza • Relációs és boolean operátorok • Részletek: JMS 1.1 specifikáció 3.8-as pont // Küldő: TextMessage tm = qsession.createTextMessage(); tm.setText("hello"); tm.setStringProperty("name", "fred"); qsender.send(tm); // Fogadó: QueueReceiver qr = qsession.createReceiver(q, "name='fred'"); TextMessage tm = (TextMessage)qr.receive(); String data = tm.getText(); // tm.getStringProperty("name").equals("fred") -- garantált!

  35. Request-response • Szinkron hívás szimulálása • Egy TemporaryQueue (vagy TemporaryTopic) jön létre, a JMSReplyTo automatikusan erre mutat • A fogadó kinyeri a fejlécet és oda válaszol // Kérő: QueueRequestor qreq = newQueueRequestor(qsession, queue); TextMessage tmin = qsess.createTextMessage(); tmin.setText("Hello"); TextMessage tmout = (TextMessage)qreq.request(tmin); // blokkol // Válaszoló: Message msg = qreceiver.receive(); Destination reply = msg.getJMSReplyTo(); TextMessage tmout = qsess.createTextMessage(); tmout.setText("Hi yourself"); QueueSender qs = qsess.createSender((Queue)reply); qs.send(tmout);

  36. Tranzakciók • Üzenetek csoportosítása atomi feldolgozáshoz • Kézbesítés garantált ACID feltételekkel • Tranzakciós Session • JTA-val integrálható (elosztott tranzakció) • Commit-ra: • mindel elküldött üzenet kézbesítésre kerül • minden fogadott üzenet visszaigazolásra kerül boolean tx = true; int ackmode = Session.AUTO_ACKNOWLEDGE; QueueSession qsession = qcon.createQueueSession(tx, ackmode); TextMessage tm = qsession.createTextMessage(); tm.setText("hello"); qsender.send(tm); tm = qsession.createTextMessage(); tm.setText("world"); qsender.send(tm); // itt qsession.commit()-ra mindkét üzenet elküldésre kerülne // itt qsession.abort()-ra mindkét üzenet elveszne

  37. MSMQ: Microsoft Message Queue

  38. MSMQ: Microsoft Message Queue • Microsoft operációs rendszereken • Jelenlegi verzió: 4.0 • Windows Vista, Windows Server 2008 • Támogatja a legfontosabb üzenetkezelési feladatokat: • szinkron és aszinkron működés • lazán- és erősen csatolt műveletek • tranzakciós küldés/fogadás • prioritások • határidők • szűrés • .NET interfész: • Névtér: System.Messaging • DLL: System.Messaging.dll

  39. Programozói modell • Queue: • 1. MessageQueue létrehozása • 2. property-k, szűrők beállítása • Küldés: • 1. Message létrehozása, kitöltése • 2. Send() • Fogadás: • 1. Formatter létrehozása • 2. Message kiolvasása • 3. kicsomagolás

  40. MessageQueue létrehozása • Már léteznie kell a Queue-nak a gépen • A MessageQueue csak egy csomagoló • A Queue neve case-insensitive string queueName = @".\private$\myqueue"; if (MessageQueue.Exists(queueName)) { using (MessageQueue myQ = newMessageQueue(queueName)) { //... } }

  41. Message létrehozása • Message objektum példányosítása • Tartalom kitöltése • Label megadása: alkalmazás által definiált azonosító • Extension megadása: alkalmazás által definiált plusz infó byte-tömbként // Konstruktorban feltöltve: using (MessageQueue myQ = newMessageQueue(queueName)) { Message msg = newMessage("Hello, MSMQ!"); msg.Label = "Greetings"; } // Vagy a Body property-vel: using (MessageQueue myQ = newMessageQueue(queueName)) { Message msg = newMessage(); msg.Body = "Hello, MSMQ!"; msg.Label = "Greetings"; }

  42. Message elküldése • MessageQueue.Send() átadva paraméterként az üzenetet • Overload-olt változat: a Label is megadható • a Label-t az MSMQ figyelmen kívül hagyja, csak az alkalmazás számára releváns using (MessageQueue myQ = newMessageQueue(queueName)) { Message msg = newMessage("Hello, MSMQ!"); myQ.Send(msg); myQ.Send(msg, "greetingmsg"); }

  43. Message fogadása • Formatter létrehozása • Receive(), Peek() vagy GetAllMessages() meghívása • a Body property kiolvasása using (MessageQueue myQ = newMessageQueue(queueName)) { myQ.Formatter = newXmlMessageFormatter(newType[] {typeof(string)}); // első üzenet kiolvasása, de a sorban hagyása: Message msg = myQ.Peek(); // első üzenet kiolvasása és törlése a sorból: Message msg2 = myQ.Receive(); Console.WriteLine((string)(msg.Body)); }

  44. Üzenetek szűrése • A MessageReadPropertyFilter azt adja meg, mely property-ket szeretnénk kiolvasni • A property értéke alapján nincs szűrés! using (MessageQueue myQ = newMessageQueue(queueName)) { myQ.Formatter = newXmlMessageFormatter(newType[] {typeof(string)}); // A Label-t és az Extension-t is olvassa ki: myQ.MessageReadPropertyFilter.Label = true; myQ.MessageReadPropertyFilter.Extension = true; Message m = myQ.Receive(); Console.WriteLine(m.Label); // Az üzenet címkéje Console.WriteLine(m.Priority); // Mindig 0 lesz }

  45. Request-response • Message.ResponseQueue property tartalmazza a válasz queue-t • A kérő a Send() meghívása előtt beállítja az értékét • A válaszoló erre válaszol egy Receive() vagy Peek() után • Teljesen alkalmazásszintű, alapértelmezett értéke null using (MessageQueue responseQueue = newMessageQueue(@".\private$\responseQueue")) using (MessageQueue senderQueue = newMessageQueue(@".\private$\senderQueue")) { responseQueue.Formatter = newXmlMessageFormatter(newType[] { typeof(string) }); Message msg = newMessage("Hello, there!"); msg.ResponseQueue = responseQueue; senderQueue.Send(msg); Message responseMsg = responseQueue.Receive(); Console.WriteLine(responseMsg.Body); }

  46. Queue-k típusai • Alkalmazás szintű sor (Application Queue) • adminisztrátorok vagy programozók által létrehozva • négy szerepkör: • destination • administration • response • report • Rendszersor (System Queue) • az MSMQ hozza létre • típusai: • dead-letter • journal • connector

  47. Application Queues • Destination Queues • tárolja az üzeneteket az alkalmazás számára • típusai: • public: directory service-be regisztrált • private: minimális directory overhead, nincs lookup • Administration Queues • a rendszer által generált visszaigazolásokat tárolja • Response Queues • a kérés üzenetekre küldött válaszokat tárolja • Report Queues • publikus queue • monitorozó üzeneteket tárol a route-olásról

  48. System Queues • Dead-letter Queues • a kézbesíthetetlen üzenetek végső nyughelye • minden egyes queue-ra külön • csak olvasható, közvetlenül nem küldhető bele üzenet • Journal Queues • az elküldött üzenetek másolatait tárolja • jobb QoS-t biztosít • csak olvasható, közvetlenül nem küldhető bele üzenet • olyan, mint az adatbázis log • Connector Queues • route-olásnál használt • tárolásra és forward-olásra

  49. Üzenet tartalma • Bármilyen objektum lehet, ha a Formatter kezelni tudja • Három lehetséges Formatter: • ActiveXMessageFormatter • BinaryMessageFormatter: .NET szerializálás • XmlMessageFormatter (ez az alapértelmezett): .NET XmlSerializer-t használ • Küldéskor a Message.Formatter property-t kell beállítani • Fogadáskor a MessageQueue.Formatter property-t

  50. Aszinkron fogadás • Eseménykezelés segítségével: ReceiveCompleted • A fogadó szálat a nem blokkoló BeginReceive függvénnyel lehet elindítani • A Delegate meghívódik egy thread-pool szálból • az EndReceive meghívásával kapja meg az üzenetet • utána explicit meg kell hívnia a BeginReceive-et is! • Ugyanígy működik a PeekCompleted / BeginPeek / EndPeek hármas

More Related