No. 240 Marcel Gnoth, NTeam GmbH Message Queueing Stille Post mit dem.Net-Framework
Zur Person Dipl. Inf. Marcel Gnoth NTeam GmbH, Berlin Senior Consultant, Trainer VB6, COM, Datenbanken Verteilte Informationssysteme Und.....Net
Überblick Einführung MSMQ Vorstellen des Anwendungsszenarios MSMQ im Detail
Message Queueing Einführung
Message – Queueing Transport von Nachrichten zwischen Computern
Einführung Konzepte Asynchrone Abarbeitung von Aufgaben Empfänger oder Sender kann Offline sein Nachrichten werden zwischengepuffert Aktiver Austausch von Informationen zwischen Programmen / Computern Pushen der Infos
Einführung Technik Versionen NT4: MSMQ 1.0 (Option Pack) ab Win2k MSMQ 2.0 Bestandteil des Win2k / WinXP Setup Active Directory / Domänen Controller MQIS Message Queue Information Store Public Queues Aktive Directory Ohne MQIS nur Private Queues
Einführung Programmieren Referenz auf System.Messaging MessageQueue Zugriff auf eine Warteschlange Public Queues Sind im MQIS eingetragen Private Queues Ohne Active Directory Message Nachrichten, die verschickt oder empfangen werden
Öffnen einer Queue MessageQueue.Create (Path As String) New MessageQueue (Path As String) MessageQueue.Exists (Path As String) Imports System.Messaging Private WithEvents m_JobQueue As MessageQueue Sub Test() m_JobQueue = New MessageQueue _ ("Gengar\Private$\Jobs") End Sub Dim mqs As MessageQueue() = _ MessageQueue.GetPrivateQueuesByMachine("Gengar")
Wie findet MSMQ eine Queue? Mit MQIS (Active Directory) Public und Private Path - Property Label - Property FormatName - Property Ohne MQIS Nur Private FormatName - Property
Öffnen mit Path Zugriff auf MQIS Kein Offline Private Queues nur lokal öffnen Dim mq As MessageQueue, s As String s = "Gengar\Jobs" 'Public s = "Gengar\Private$\Jobs"'Private mq = New MessageQueue(s)
Öffnen mit Label Label = Name einer Queue Sucht über MQIS die Queue Langsamer, da Zugriff auf MQIS Kein Offline Nur Public Queues Dim myQueue As New MessageQueue("Label:TheLabel")
Öffnen mit FormatName Offline Mode Ohne MQIS Schnellste und flexibelste Methode FormatName:Public=5A5F7535-AE9A-41d4-935C-845C2AFF7112 FormatName:DIRECT=SPX:NetworkNumber;HostNumber\QueueName FormatName:DIRECT=TCP:IPAddress\QueueName FormatName:DIRECT=OS:MachineName\QueueName FormatName:DIRECT=OS:MachineName\Private$\QueueName Dim myQueue As New MessageQueue _ ("FormatName:DIRECT=OS:Gengar\private$\Jobs")
Senden einer Nachricht Queue öffnen Send Methode mit einen String oder einem Objekt aufrufen Object wird serialisiert XML ist Standardformat z.B. DataSets verschicken msgQ.Send(myObject, "Message Label")
Senden mit explizitem Message - Objekt Konfigurieren der Message – Parameter Format, Verschlüsselung, TimeOuts Formate für Serialisierung: XMLMessageFormatter BinaryMessageFormatter ActiveXMessageFormatter With myMsg.Label = "Job " + theJob.ID.Formatter = New BinaryMessageFormatter().AppSpecific = 34.Priority = MessagePriority.VeryHigh.Body = theJob End With
Demo: Nachricht versenden
Inhalt einer Queue ansehen Peek – Methode GetEnumerator Dim eM As IEnumerator = mqJobs.GetEnumerator() lstJobMessages.Items.Clear() Do While eM.MoveNext() Dim q As Message q = CType(eM.Current, Message) lstJobMessages.Items.Add(q.Label) Loop myMsg = m_JobQueue.Peek()
Nachricht empfangen Receive BeginReceive Asynchrones Empfangen Dim msg As Message = mqResults.Receive() mqResults.BeginReceive() Private Sub mqResults_ReceiveCompleted(..., _ ByVal e As...ReceiveCompletedEventArgs) _ Handles mqResults.ReceiveCompleted Dim myMsg As System.Messaging.Message myMsg = e.Message End Sub
Format der Nachricht Body ist vom Typ Object Mögliche Typen festlegen Formatter initialisieren Für Deserialisierung zuständig Dim m_MsgTargetTypes(1) As Type m_MsgTargetTypes(0) = GetType(String) m_MsgTargetTypes(1) = GetType(Job) Dim m_XmlMsgFrmt As XmlMessageFormatter m_XmlMsgFrmt = New _ XmlMessageFormatter(m_MsgTargetTypes)
Nachrichten Body auspacken Der Formatter deserialisiert den Body Erzeugt gewünschtes Objekt Dim j As Job, s As String myMsg.Formatter = m_XmlMsgFrmt If TypeOf (myMsg.Body) Is Job Then 'Job Object j = CType(myMsg.Body, Job) ProcessJob(j) Else 'String s = CStr(myMsg.Body) Console.Write(s) End If
Woher weiß der Formatter das? Durch Reflection kann zur Laufzeit ein Object untersucht werden Klasse als kennzeichnen Wird automatisch serialisiert Public Class Job Public Name As String End Class
Demo Nachricht empfangen
MSMQ in der Praxis Job Shop Scheduling als Anwendungsszenario
Job Shop Scheduling Viele Jobs die lange dauern Arbeit auf mehrere Rechner verteilen Ergebnisse werden eingesammelt Eine oder mehrere Queue(s) mit Aufträgen Queue(s) mit Ergebnissen
Job Shop Scheduling
Projekte JobShopComponent (Dll) Klassen Job und Jobs Kapselt Aufträge JobShopManager (Exe) Erzeugt Jobs Sammelt Ergebnisse ein Kontrolliert Bestätigungen JobShopWorker (Exe) Nimmt Job aus Queue Verarbeitet Job Sendet Ergebnis in Queue
JobShopManager.vbpj frmCreatorMain Erzeugt Jobs / Nachrichten Stellt Nachrichten in Job-Queue
JobShopManager.vbpj frmResult Überwacht Result-Queue Zeigt Ergebnisse an
JobShopWorker.vbpj Lauscht an der Job-Queue Bearbeitet Jobs Sendet Ergebnisse an Result-Queue
Live - Demo
MSMQ im Detail Acknowledgements TimeOuts Journlaing Transaktionen
Time Outs Was passiert, wenn Nachricht nicht gelesen wird? MSMQ informiert wenn Zeiten zum Übermitteln und zum Lesen überschritten werden Properties: TimeToReachQueue TimeToBeReceived
Acknowlegdgements MSMQ schickt Bestätigungs - Nachrichten ReachQueue: Erreichen der Queue Receive: Aus der Queue entnommen AcknowledgeTypes: None FullReachQueue, PositiveArrival NotAcknowledgeReachQueue FullReceive, NotAcknowledgeReceive NegativeReceive, PositiveReceive
Acknowledgements AdministratorQueue: Wurde der Nachricht beim Versenden übergeben Benachrichtigungen landen in dieser Queue Ganz normale Queue Nach dem Senden ist Message.ID gesetzt theMsg.TimeToBeReceived = New TimeSpan(0, 0, 20) theMsg.AcknowledgeType = _ AcknowledgeTypes.FullReachQueue Or _ AcknowledgeTypes.FullReceive theMsg.AdministrationQueue = m_JobAckQueue m_JobQueue.Send(theMsg) myJob.MQMessageID = theMsg.Id 'für CorrelationID
Acknowledgement Nachrichten MessageType: Acknowledgment CorrelationId: Kennung der betroffenen Nachricht Beim Öffnen der Ack- Queue: Dim j As Job, s As String j = m_Jobs.ItemByMQMessageID(theMsg.CorrelationID) s = Msg.Acknowledgment.ToString m_JobAckQueue.MessageReadPropertyFilter.CorrelationId = True
Journaling Überwacht Transport der Nachrichten zwischen einzelnen Computern Nur bei Versand zwischen Computern! Journal-Queues: System-Queues Individuelle für jede Queue Eine Systemweite Journal-Queue
Journaling Szenario: Negatives Acknowledgement überwachen Betroffene Nachricht aus der Journal- Queue holen (ReceiveByID) System – Journal – Queue Queue eigene Journal - Queue theMsg.UseJournalQueue = True theQueue.UseJournalQueue = True
Demo
Transaktion Interne MSMQ Transaktionen DTC – Transaktionen Distributed Transaktion Coordinator MSMQ, SQL-Server, Oracle, Sybase Ressource-Manager arbeiten mit DTC zusammen Infos: us/dnbda/html/bdadotnettransact1.asp us/dnbda/html/bdadotnettransact1.asp
Fazit - MSMQ Einfacher Daten (Objekt) – Austausch in der Windowswelt Bridges in andere Welten Wann Einsetzen: Rechnerübergreifende Kommunikation Asynchrone Abarbeitung von Programmen Disconected Programmierung
Fazit - Queues Public Queues sind bequemer nur bei solidem Active Directory Private Queues Schneller, weniger Overhead Ermöglichen Offline – Betrieb kein Domänen- oder Active Directory Controller vorhanden
Fazit – Formate XML: Kleine Datenmenge BLOBs ??? Gut lesbar Binary: Weniger Overhead, effizienter Nur wenn XML keinen Sinn macht Serialisierung kann kontrolliert werden
Links Basic Pro 5/2001 Nachrichtenbasierte Informationssysteme auf MSDN suchen Accessing Message Queues us/dnbda/html/bdadotnetasync1.asp us/dnbda/html/bdadotnetasync1.asp Reliable Messaging with MSMQ and.NET us/dnbda/html/bdadotnetasync2.asp us/dnbda/html/bdadotnetasync2.asp MSMQ Home-Page
Fragen? Uff...