Dieser Artikel wurde maschinell übersetzt.

Windows Azure-Insider

Windows Azure-Dienstbus: Nachrichtenmuster mithilfe von Sitzungen

Bruno Terkaly
Ricardo Villalobos

Bruno Terkaly Ricardo VillalobosIn einem unserer früheren Artikeln diskutierten wir die Bedeutung des Einsatzes von Messagingmuster in der Wolke, um Lösungen zu entkoppeln und zu fördern--Maßstab Softwarearchitekturen. (Finden Sie unter "Vergleich von Windows Azure Queues and Service Bus Queues" unter msdn.microsoft.com/magazine/jj159884.) Queuing ist einer dieser messaging-Muster und Windows Azure Platform bietet zwei Hauptoptionen zur Umsetzung dieses Konzepts: Warteschlange Storage Services und Service-Bus-Warteschlangen, beide Szenarien mehrere Verbraucher wo konkurrieren beinhalten, empfangen und verarbeiten die Nachrichten in einer Warteschlange. Dies ist das kanonische Modell für Unterstützung Variable Arbeitslasten in der Wolke, wo Empfänger dynamisch hinzugefügt oder entfernt werden können auf die Größe der Warteschlange, bietet eine laden-Ausgleich/Ausfallsicherung für Back-End (siehe Abbildung 1).

Queuing Messaging Pattern: Each Message Is Consumed by a Single Receiver
Abbildung 1 Warteschlangen Messaging Muster: Jede Nachricht wird von einem einzelnen Empfänger genutzt.

Auch wenn das Warteschlange messaging Muster eine großartige Lösung für einfache Entkopplung ist, gibt es Situationen, in denen jeder Empfänger seine eigene Kopie der Nachricht, mit der Option verwerfen einige Nachrichten entsprechend bestimmten Regeln erfordert. Ein gutes Beispiel für diese Art von Szenario zeigt sich an Abbildung 2, das zeigt einer gemeinsamen Herausforderung, dass Einzelhandel Gesicht beim Senden von Informationen an mehrere Branchen, wie die neuesten Produkte-Katalog oder eine aktualisierte Preisliste Unternehmen.

Publisher/Subscriber Messaging Pattern: Each Message Can Be Consumed More Than Once
Abbildung 2 Verleger/Abonnent Messaging Muster: Jede Nachricht kann mehr als einmal verzehrt werden.

Diesen Situationen ist das Muster der Verleger/Abonnent eine bessere Passform, wo Ausdrücken die Empfänger einfach ein Interesse an einer oder mehreren Nachrichtenkategorien, Herstellen einer Verbindung zu einer unabhängigen Abonnement, das eine Kopie der Nachrichtenstream enthält. Windows Azure Service Bus implementiert das Verleger/Abonnent messaging-Muster durch Themen und Abonnements, das erheblich die Fähigkeit zur Steuerung der Verteilung Nachrichten verbessert, basierend auf der unabhängigen Regeln und filtern. In diesem Artikel erklären wir wie diese mit ein einfachen realen Szenario Windows Azure Service Bus-Funktionen angewendet, vorausgesetzt, die folgenden Anforderungen:

  1. Produkte soll, in Abhängigkeit von der Katalogseite empfangen werden.
  2. Einige der Geschäfte tragen nicht bestimmten Katalogkategorien und Produkte in diesen Kategorien für jedes Geschäft heraus gefiltert werden soll.
  3. Neue Kataloginformationen sollte nicht auf das Shop-System angewendet werden, bis alle Nachrichten angekommen sind.

Die Codebeispiele in diesem Artikel wurden mit Visual Studio 2012 mit c# als Programmiersprache erstellt. Sie benötigen auch das Windows Azure SDK Version 1.8 für .NET Entwickler und Zugriff auf ein Windows-Azure-Abonnement.

Die Messaging-Blaupause einrichten für das Projekt

Bevor Sie Code schreiben, müssen Sie die verschiedenen Entitäten (Themen und Abonnements) zu definieren, die Bestandteil der messaging-Workflow werden. Dies kann erreicht werden, indem Sie auf dem Windows Azure Portal unter manage.windowsazure.com. Melden Sie sich mit Ihren Anmeldeinformationen und folgen Sie diesen Schritten:

  1. Klicken Sie auf neu erstellen, auf der unteren linken Ecke Verwaltungsportal.
  2. Klicken Sie auf das Symbol des APP-SERVICES, dann auf SERVICE BUS Thema und schließlich auf CUSTOM erstellen (siehe Abbildung 3).
  3. Im ersten Dialog-Fenster geben Sie den Namen Thema und wählen Sie die entsprechende Region und Windows-Azure-Abonnement-ID. Wenn dies Ihre erste Namespace im ausgewählten Bereich ist, wird der Assistent eine Namespace-Warteschlange vorschlagen: [Ihr Entitätsname]-ns. Sie können diesen Wert ändern.
  4. Klicken Sie auf den nächsten Wendemarke (nach rechts zeigenden Pfeil) die übrigen Eigenschaften einfügen. Sie können die Standardwerte beibehalten. Klicken Sie auf das Häkchen, das Thema zu erstellen.
  5. Klicken Sie auf den Service Bus-Symbol auf der linken Navigationsleiste erhalten Sie eine Liste der Namespaces. Beachten Sie, dass den aufgeführten sofort Namespace möglicherweise nicht angezeigt. Es dauert einige Sekunden, um den Namespace zu erstellen und aktualisieren die Portalschnittstelle.
  6. Wählen Sie das Thema, das Sie gerade, aus der Liste erstellt, und klicken Sie auf Schlüssel, die auf der Unterseite des Bildschirms zu finden. Notieren Sie die vollständige Verbindungszeichenfolge für die spätere Verwendung.
  7. Klicken Sie oben auf dem Bildschirm Windows Azure Portal auf Abonnements, und dann auf CREATE A NEW SUBSCRIPTION. Die Popup-Dialogfeld geben Sie einen Namen (in unserem Beispiel verwendeten wir "Store1Sub"), und klicken Sie auf den Pfeil, um fortzufahren.
  8. Übernehmen Sie im nächsten Bildschirm die Standardwerte, aber müssen Sie die Option aktivieren-Sitzungen zu überprüfen. Klicken Sie auf das Häkchen, um das Abonnement zu erstellen. Sitzungen werden von Abonnenten zum Abrufen von Nachrichten in der Reihenfolge verwendet werden.
  9. Wiederholen Sie die Schritte 7 und 8 für jedes der drei Läden.

Creating a New Service Bus Topic Using the Windows Azure Portal
Abbildung 3 erstellen ein neues Service-Bus-Thema mit Windows Azure Portal

Nachdem die Themen und die Abonnements erstellt wurden, können Sie diese auch direkt in Visual Studio zugreifen. Hierzu öffnen Sie Server-Explorer (Ansicht | Server-Explorer), und erweitern Sie den Knoten Windows Azure Service-Bus (siehe Abbildung 4). Mit der rechten Maustaste auf den Windows Azure Service-Bus-Knoten, und wählen Sie neue Verbindung hinzufügen. Geben Sie den Namespace-Namen, Ausstellername (in der Regel "Hersteller") und Emittenten Access Key bei der Windows-Azure-Namespace, in das Portal erstellt wurde eingetragen.

Creating a Service Bus Topic and Subscriptions Using the Visual Studio Tools
Abbildung 4 Erstellen eines Service-Bus-Themas und Abonnements mithilfe der Visual Studio-Tools

Denken Sie daran, dass es möglich ist, programmgesteuert erstellen und verwalten diese Entitäten mit Klassen im Namespace Microsoft.ServiceBus.Messaging, einschließlich TopicClient und SubscriptionClient, die später in diesem Artikel verwendet werden.

Sobald die Grundstruktur für die messaging-Workflow erstellt wurde, werden wir simulieren Verkehr mit zwei Konsolen-Anwendungen in Visual Studio erstellt, wie in Abbildung 5. Die erste Konsolenanwendung, MSDNSender, werden den Produktkatalog senden. Die zweite MSDN­Receiver, erhalten die Informationen in den einzelnen Läden. Hier analysieren wir den Code in den folgenden Abschnitten. Im Pub/Sub-Muster der MSDNSender ist der Verleger und der MSDNReceiver ist der Abonnent.

Visual Studio Solution to Simulate the Products Catalog Scenario
Abbildung 5 Visual Studio-Projektmappe, das Produktkatalog-Szenario zu simulieren

Senden den Produktkatalog vom Hauptsitz

Wie Sie, in sehen können Abbildung 2, Sitz (der Hersteller) sendet Nachrichten an ein Thema. Diese Logik wird durch den Code in die Hauptdatei Program.cs, ein Teil des Projektes MSDNSender dargestellt. Program.cs kapselt die Logik und den Code, um eine Liste der Produkte zum Thema als einzelne Nachrichten senden. Werfen Sie einen Blick auf die verschiedenen Bereiche, beginnend mit der Main-Methode. Beachten Sie, dass zunächst erstellen wir einen Client für das Thema, wie folgt:

// Create a topicClient using the
// Service Bus credentials
TopicClient topicClient =
  TopicClient.CreateFromConnectionString(
  serviceBusConnectionString, topicName);

Sobald eine TopicClient erstellt wurde, kann der Herausgeber Nachrichten benutze es senden. Die Liste der Produkte gesendet werden wird gespeichert, in einer XML-Datei namens ProductsCatalog.xml, das eine Liste von 10 Produkt Entitäten enthält, die in ein Array von Objekten umgewandelt werden. Die Produkte werden dann in den Katalog und Produkt-Klassen in der Datei Product.cs gespeichert zugeordnet bekommen:

// Deserialize XML file with Products, and store them in an object array
Catalog catalog = null;
string path = "ProductsCatalog.xml";
XmlSerializer serializer = new XmlSerializer(typeof(Catalog));
StreamReader reader = new StreamReader(path);
catalog = (Catalog) serializer.Deserialize(reader);
reader.Close();

Jedes Produkt im Katalog Array stellt die Struktur dargestellt Abbildung 6.

Abbildung 6-Klassendarstellung für Produkte im Katalog

public class Product
  {
    [System.Xml.Serialization.XmlElement("ProductId")]
    public string ProductId { get; set; }
    [System.Xml.Serialization.XmlElement("ProductName")]
    public string ProductName { get; set; }
    [System.Xml.Serialization.XmlElement("Category")]
    public string Category { get; set; }
    [System.Xml.Serialization.XmlElement("CatalogPage")]
    public int CatalogPage { get; set; }
    [System.Xml.Serialization.XmlElement("MSRP")]
    public double MSRP { get; set; }
    [System.Xml.Serialization.XmlElement("Store")]
    public string Store { get; set; }
  }

Innerhalb der Schleife Array ein Aufruf der Methode CreateMessage extrahiert verschiedene Eigenschaften von Product-Objekten und weist sie auf die Nachricht gesendet werden soll. Zwei Eigenschaften erfordern besondere Aufmerksamkeit:

if (isLastProductInArray)
  message.Properties.Add("IsLastMessageInSession", "true");
message.SessionId = catalogName;

Sitzungen sind äußerst wichtig, denn sie ermöglichen den Empfänger zu bestimmen, ob alle Nachrichten, die auf eine bestimmte logische Gruppe gehören angekommen sind. In diesem Fall sind wir durch die SessionId Message-Eigenschaft festlegen, angeben, dass der Empfänger nicht die Kataloginformationen bis verwenden, nachdem alle Nachrichten mit dem gleichen Wert CatalogName angekommen sind. Wir sind auch für das letzte Produkt im Array, das eine neue Eigenschaft hinzufügen: IsLastMessageInSession, die es erlauben, wird die Empfänger zu bestimmen, ob die letzte Nachricht in der Sitzung angekommen ist und der Katalog können vollständig verarbeitet werden. Abbildung 7 MSDNSender ausgeführt wird.

Execution of the MSDNSender Project
Abbildung 7 Ausführung des Projektes MSDNSender

Erhalt des Produktkatalogs mit Abonnements in den Läden

Nun, den Katalog und die Produkte wurden ausgeschickt, um das Thema und in den verschiedenen Abonnements kopiert, wenden wir unsere Aufmerksamkeit auf das MSDNReceiver-Projekt, in dem Nachrichten empfangen und verarbeitet werden. Beachten Sie, dass der Code in der Main-Methode der Datei Program.cs, ein Client erstellt für das Abonnement auf Informationen durch den Benutzer über ein Console.Read-basierte­Befehl Linie. Benutzer sollen ihre Speicher, eingeben, die spiegelt die Nachrichten, die sie erhalten möchten. Kurz gesagt, jede Filiale Filiale nur Nachrichten betrifft, die für dieses Speichers gelten:

Console.WriteLine("Enter Store Number");
  string storeNumber = Console.ReadLine();
  Console.WriteLine("Selecting Subscription for Store...");
  // Create a Subscription Client to the Topic
  SubscriptionClient subscriptionClient =
    SubscriptionClient.CreateFromConnectionString(
    serviceBusConnectionString, topicName,
    "Store" + storeNumber.Trim() + "Sub",
    ReceiveMode.PeekLock);

Denn wir von Nachrichten aus der Abonnements basierend auf Sitzungen empfangen (wie im vorherigen Abschnitt beschrieben) müssen wir die nächsten anfordern mithilfe der folgenden Codezeile:

MessageSession sessionReceiver =
  subscriptionClient.AcceptMessageSession(TimeSpan.FromSeconds(5));

Im Grunde, was bedeutet, dass der Client verarbeitet werden Nachrichten im Abonnement überprüfen wird — diejenigen, deren SessionId-Eigenschaft nicht null ist — und wenn keine solchen Nachrichten innerhalb von fünf Sekunden auftreten, wird die Anforderung Zeit ­heraus, die Receiver-Anwendung beenden. Auf der anderen Seite, wenn eine Sitzung gefunden wird, wird die ReceivingSessionMessages-Methode aufgerufen werden. Bevor wir in dieses Stück Code springen, sprechen wir über das Konzept der Sitzungszustand die ermöglicht es dem Entwickler Informationen speichern, die verwendet werden können, während Nachrichten, die an dieselbe Transaktion gehören empfangen werden. In diesem Fall verwenden wir Sitzungszustand zu "erinnern", der letzten Katalogseite, die empfangen wurde, sowie die Nachrichten — Produkte —, die ankamen, out of Order.

Auf dieser Basis ist hier der Workflow im Code:

  1. Die aktuelle Meldung in der ReceiveSession erhalten­Nachrichten-Methode (siehe Abbildung 8), die stützt sich auf die ProcessMessage-Methode (Abbildung 9), sie zu verarbeiten.
  2. Innerhalb der ProcessMessage-Methode wenn die Nachricht außerhalb der Reihenfolge ist, wird es automatisch verzögert und seine ID im Sitzungszustand gespeichert. Ansonsten hat es als "erledigt" markiert und aus dem Abonnement entfernt. Auch die nächste Folge erwartet – Katalogseite — in einer Sitzung gespeichert ist.
  3. Nachdem die aktuelle empfangene Nachricht verarbeitet wurde, der nachfolgende Code in ReceiveSessionMessages sucht latente Nachrichten-IDs in der Sitzung, und versucht, sie wieder basiert auf der neuesten Katalog-Seite zu verarbeiten.
  4. Nachdem alle Nachrichten für die Sitzung eingegangen sind, wird der Empfänger geschlossen.

Abbildung 8 die ReceivedSessionMessages-Methode im Code

static void ReceiveSessionMessages(MessageSession receiver)
  {
    // Read messages from subscription until subscription is empty
    Console.WriteLine("Reading messages from subscription {0}", 
      receiver.Path);
    Console.WriteLine("Receiver Type:" + receiver.GetType().Name);
    Console.WriteLine("Receiver.SessionId = " + receiver.SessionId);
    SequenceState sessionState = GetState(receiver);
    BrokeredMessage receivedMessage;
    while ((receivedMessage = receiver.Receive()) != null)
    {
      string sessionId = receiver.SessionId;
      ProcessMessage(receivedMessage, ref sessionState, receiver);
      while (sessionState.GetNextOutOfSequenceMessage() != -1)
      {
        // Call back deferred messages
        Console.WriteLine("Calling back for deferred message: Category {0},
          Message sequence {1}", receiver.SessionId,
            sessionState.GetNextSequenceId());
        receivedMessage = receiver.Receive(
          sessionState.GetNextOutOfSequenceMessage());
        ProcessMessage(receivedMessage, ref sessionState, receiver);
      }
      if (receivedMessage.Properties.ContainsKey(
        "IsLastMessageInSession"))
        break;
    }
    SetState(receiver, null);
    receiver.Close();
  }

Abbildung 9 die ProcessMessage-Methode im Code

static void ProcessMessage(BrokeredMessage message, ref SequenceState sessionState,
  MessageSession session = null)
  {
    if (session != null)
    {
      int messageId = Convert.ToInt32(message.Properties["CatalogPage"]);
      if (sessionState.GetNextSequenceId() == messageId)
      {
        OutputMessageInfo("RECV: ", message, "State: " + "RECEIVED");
        sessionState.SetNextSequenceId(messageId + 1);
        message.Complete();
        SetState(session, sessionState);
      }
      else
      {
        Console.WriteLine("Deferring message: Category {0}, Catalog Page {1}",
          session.SessionId, messageId);
        sessionState.AddOutOfSequenceMessage(messageId, 
          message.SequenceNumber);
        message.Defer();
        SetState(session, sessionState);
      }
    }
    Thread.Sleep(receiverDelay);
  }

Denken Sie daran, dass für dieses Projekt, latente Message-IDs im Sitzungszustand gespeichert werden und möglicherweise verloren gehen. In einer Produktionsumgebung empfehlen wir irgendeine Art von permanenten Speicher (Windows Azure Tabellen ist eine Option) für diesen Zweck. Hinweis: Wenn die Nachricht die Eigenschaft IsLastMessage enthält­SessionInSession (während des sendenden Prozesses festgelegt), ist die Sitzung-Schleife beendet. Die Ausgabe für das MSDNReceiver-Projekt in gesehen werden kann Konsole Abbildung 10.

Execution of the MSDNReceiver project
Abbildung 10-Ausführung des Projektes MSDNReceiver

Windows Azure Service Bus Abonnements geben Ihnen die Möglichkeit, bestimmte Regeln erstellen, die Nachrichten zu filtern, bevor sie verbraucht sind. In diesem Fall wäre es relativ einfach eine Regel erstellen, die Alterszugehörigkeit Produkte nach Kategorie oder nach Shop-Nummer (die wir in diesem Projekt wird ignoriert). Regeln können programmgesteuert, direkt im Windows Azure Portal oder über Visual Studio-Tools erstellt werden.

Zusammenfassung

Windows Azure Service Bus bietet eine erstaunlich robuste und flexible Umsetzung der Publish/subscribe-Muster. Durch den Einsatz von Themen und Abonnements können viele verschiedene Szenarios angesprochen werden. Unterstützung von mehreren Absendern Senden von Nachrichten an mehrere Empfänger, kombiniert mit der Fähigkeit zum logisch gruppieren und Sortieren von Nachrichten, eröffnet Ihnen eine Welt von Möglichkeiten für den modernen Entwickler. Darüber hinaus macht wird zur verfolgen eine persistente Sitzung nutzen es einfach logisch Gruppieren von Nachrichten und ihre Abfolge zu steuern. In einer Welt, in denen verteilte Umgebungen die Norm sind, ist es entscheidend für heutigen Software-Architekten arbeiten in der Wolke, Grundlegendes zur messaging-Muster und die Werkzeuge um sie herum zu verwenden.

Bruno Terkaly arbeitet als Entwicklungsexperte für Microsoft. Seine fundierten Kenntnisse basieren auf mehreren Jahren Erfahrung in der Programmierung in unterschiedlichsten Plattformen, Sprachen, Frameworks, SDKs, Bibliotheken und APIs. Er schreibt Code, Blogs und referiert live über die Erstellung von cloudbasierten Anwendungen, insbesondere mit der Windows Azure-Plattform.

Der erfahrene Softwarearchitekt Ricardo Villalobos  erstellt seit über 15 Jahren Anwendungen für Unternehmen in der Supply-Chain-Management-Branche. Er besitzt verschiedene Microsoft-Zertifizierungen sowie einen Master-Abschluss in Businessadministration der University of Dallas. Er arbeitet als Cloudarchitekt in der Windows Azure CSV-Inkubationsgruppe für Microsoft.

Unser Dank gilt dem folgenden technischen Experten für die Durchsicht dieses Artikels: Abhishek Lal