Glengamoi (Forum) · AspHeute · .NET Heute (RSS-Suche) · AspxFiles (Wiki) · .NET Blogs

Asynchrone Programmierung mit Message Queues

Geschrieben von: Christoph Wille
Kategorie: C#

This printed page brought to you by AlphaSierraPapa

Ein Problem sowohl für Web Sites als auch "normale" Anwendungen sind externe "Komponenten", die entweder über eine langsame Verbindung angesprochen werden müssen, oder (sehr) lange zur Abarbeitung brauchen. Ist man nicht gezwungen auf das Resultat zu warten, kann man die Performance seiner Applikation enorm steigern: mit Message Queueing.

Das Message Queueing hat mit dem NT 4 Option Pack Einzug in die Windows Server Welt gehalten. Seit Windows 2000 ist es integrierter Teil des Betriebssystems, und mit .NET kann man nun in den verschiedensten Programmiersprachen bequem und einfach darauf zugreifen. Wer Message Queues in Visual Basic programmiert hat, der wird den Umstieg besonders leicht haben.

Das Hauptfeature von Message Queueing ist folgendes: garantierte Zustellung. Egal ob gerade die Verbindung zum Zielserver verfügbar ist oder nicht, die Nachricht kommt am Ziel an - und wenn nicht, dann wird man als Sender davon in Kenntnis gesetzt. Was soweit geht, daß eine solche Mißerfolgsmeldung eine gesamte Transaktion zurückrollen kann. Und man kann sogar "Queued Components" programmieren.

Heute wollen wir uns aber noch mit den einfachen Dingen des Message Queueings auseinandersetzen. Und darunter verstehe ich das Verschicken von einfachen Textnachrichten aus einer Anwendung, sowie das Abholen von Nachrichten durch eine andere Anwendung. Die sendende Anwendung könnte zB eine ASP.NET Seite sein, und die abholende ein Service auf einem anderem Server. Die sendende Anwendung ist sofort "fertig", und wie lange die abholende Anwendung dann zur Durchführung der gesendeten Anweisungen braucht ist für die sendende Anwendung nicht mehr maßgeblich.

Vorbedingung ist, daß ein Message Queue Server existiert. Für den heute vorgestellten Code reicht es, einen lokal installierten Workgroup Server zu konfigurieren. Die Installation erfolgt über Control Panel, Add/Remove Programs, Windows Components:

Der erste Schritt ist, den Typ des Server festzulegen. Um die AD Unterstützung gleich von vorne herein händisch zu konfigurieren, wählen Sie "Manually select access mode..." aus:

Im zweiten und letzten Schritt wählen Sie dann die zweite Option, und schon ist der Message Queue Server im Workgroup Modus konfiguriert.

Später kann man dann jederzeit auf Active Directory basierte Message Queue Server umsteigen. Für unsere heutigen Beispiele reicht aber bereits der kleine Workgroupserver.

Nachrichten schicken

Eigentlich würde man ja vermuten, daß der erste Schritt das Einrichten der notwendigen Message Queues sein sollte. Aber wozu händisch konfigurieren, wenn man das als Teil des Sendens automatisch mit erledigen kann (send2queue.cs)?

using System;
using System.Messaging;
   
public class MQSend 
{
   public static void Main(String[] args) 
   {
      string mqPath = ".\\private$\\MyQueue2";
      if (!MessageQueue.Exists(mqPath))
      {
         MessageQueue.Create(mqPath);
      }
      
      MessageQueue mq = new MessageQueue(mqPath);
      mq.Send("whateverdata");
   }
}

Der vorgestelle Code ist eine Consolenanwendung, kann aber leicht in eine ASP.NET Seite portiert werden (genauso wie er auch leicht nach VB.NET portiert werden kann).

Die Queue, die ich verwende, ist eine private am lokalen Server abgelegte Queue mit dem Namen MyQueue2. Als erstes kontrolliere ich, ob die Queue existiert - ist diese nicht vorhanden, lege ich sie an. Dadurch kann der erste Aufruf des Programms auch etwas länger dauern, aber dann existiert die Queue als auch die einfache Textnachricht:

Wenn man die Eigenschaften der Nachricht ansieht, findet man auch den Textinhalt der Nachricht - die wir uns nun auch wieder abholen wollen.

Nachrichten abholen & bearbeiten

Der Code zum Abholen von Nachrichten aus einer Message Queue fällt deutlich umfangreicher aus (queryqueue.cs). Der Grund hierfür ist, daß das Nichtexistieren der Queue ein fataler Fehler ist, und wir auch einige Fehlerfälle bearbeiten müssen: daß keine Nachrichten in der Queue sind, oder auch daß die Nachricht nicht unserem erwarteten Format entspricht:

using System;
using System.Messaging;
using System.IO;
using System.Runtime.Serialization;

public class MQReceive
{
    public static void Main()
    {
        string mqPath = ".\\private$\\MyQueue2";

        if ( !MessageQueue.Exists(mqPath) ) 
        {
            Console.WriteLine("The queue '" + mqPath + "' does not exist!");
            return;
        }

        MessageQueue mq = new MessageQueue(mqPath);
        ((XmlMessageFormatter)mq.Formatter).TargetTypeNames = new string[]{"System.String"};

        try 
        {
            Message m = mq.Receive(new TimeSpan(0,0,3));
            Console.WriteLine("Message: " + (string)m.Body);
        }
        catch ( MessageQueueException ) 
        {
            Console.WriteLine("There are no messages in the queue");
            return;
        }
        catch ( InvalidOperationException ) 
        {
            Console.WriteLine("The message removed from the queue is not a string");
            return;
        }
    }
}

Auch diesmal gilt, daß der Code leicht auf ASP.NET oder VB.NET portiert werden kann.

Existiert die Queue nicht (MessageQueue.Exists), wird das Programm verlassen. Nach diesem Check öffne ich die Queue, und erzeuge einen Formatter, der es mir erlaubt, die Nachricht wie gewünscht auszulesen. In diesem Falle ist es System.String, es könnte aber durchwegs ein eigens programmiertes Objekt sein (die Serialisierung findet ja immer mit XML statt).

Der Code zum auslesen und ausgeben der Nachricht ist in einem try/catch Block programmiert. Der Grund hierfür ist wie immer Exception Handling, und zwar die beiden Gründe, die ich anfangs erwähnt habe: keine weiteren Nachrichten, oder die Nachricht war kein String.

Geht alles gut, zeigt die Anwendung den Inhalt der Nachricht an. In allen anderen Fällen bekommt man eine Fehlermeldung spezifisch für die Exception angezeigt. Natürlich ist dies nur ein Beispiel - anstatt den Inhalt anzuzeigen, würde eine echte Anwendung die Daten zur Weiterverabeitung verwenden.

Schlußbemerkung

Der heutige Artikel zeigte die einfachste Art der Programmierung mit Message Queues. Obwohl das Beispiel einfach war, sollte man nicht vergessen, daß asynchrone Programmierung ein wichtiger Grundstein zu skalierbarer Software ist.

This printed page brought to you by AlphaSierraPapa

Download des Codes

Klicken Sie hier, um den Download zu starten.
http://www.aspheute.com/code/20010702.zip

Links zu anderen Sites

DotNetGerman Diskussionslisten
http://www.dotnetgerman.com/
SharpDevelop
http://www.icsharpcode.net/opensource/sd/

 

©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.