Freigeben über


MSMQ-Aktivierung

Dieses Beispiel veranschaulicht das Hosten von Anwendungen in Windows Process Activation Service (WAS), die von einer Nachrichtenwarteschlange gelesen werden. Dieses Beispiel nutzt netMsmqBinding und basiert auf dem Beispiel Bidirektionale Kommunikation. In diesem Fall handelt es sich bei dem Dienst um eine im Web gehostete Anwendung. Der Client ist selbst gehostet und gibt an die Konsole aus, um den Status eingereichter Bestellungen zu beobachten.

Tipp

Die Setupprozedur und die Erstellungsanweisungen für dieses Beispiel befinden sich am Ende dieses Themas.

Windows Process Activation Service (WAS), der neue Prozessaktivierungsmechanismus für Windows Server 2008, stellt IIS-ähnliche Features bereit, die zuvor nur für HTTP-basierte Anwendungen zur Verfügung standen, die Nicht-HTTP-Protokolle verwenden. Windows Communication Foundation (WCF) nutzt die Schnittstelle des Listeneradapters, um Aktivierungsanforderungen zu kommunizieren, die über die von WCF unterstützten Nicht-HTTP-Protokolle empfangen werden. Zu diesen gehören beispielsweise TCP, Named Pipes und MSMQ. Die Funktionalität für den Empfang von Anforderungen über Nicht-HTTP-Protokolle wird von verwalteten Windows-Diensten gehostet, die in "SMSvcHost.exe" ausgeführt werden.

Der Net.Msmq-Listeneradapterdienst (NetMsmqActivator) aktiviert in der Warteschlange befindliche Anwendungen auf der Grundlage von Nachrichten in der Warteschlange.

Der Client sendet Bestellungen aus dem Bereich einer Transaktion an den Dienst. Der Dienst empfängt die Bestellungen in einer Transaktion und verarbeitet sie. Der Dienst führt dann einen Rückruf an den Client mit dem Status der Bestellung durch. Zur Vereinfachung der bidirektionalen Kommunikation verwenden sowohl der Client als auch der Dienst Warteschlangen für Bestellungen und den Auftragsstatus.

Der IOrderProcessor-Dienstvertrag definiert die unidirektionalen Dienstvorgänge, die mit Warteschlangen funktionieren. Der Dienstvorgang nutzt den Antwortendpunkt, um Bestellstatus an den Client zu senden. Die Adresse des Antwortendpunkts ist der URI der Warteschlange, die für die Rücksendung des Auftragsstatus an den Client verwendet wird. Die Anwendung für die Auftragsverarbeitung implementiert diesen Vertrag.

[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
public interface IOrderProcessor
{
    [OperationContract(IsOneWay = true)]
    void SubmitPurchaseOrder(PurchaseOrder po, 
                                           string reportOrderStatusTo);
}

Der Antwortvertrag, an den der Bestellstatus gesendet wird, wird vom Client angegeben. Der Client implementiert den Auftragsstatusvertrag. Der Dienst verwendet den generierten Client dieses Vertrags, um den Bestellstatus an den Client zurückzusenden.

[ServiceContract]
public interface IOrderStatus
{
    [OperationContract(IsOneWay = true)]
    void OrderStatus(string poNumber, string status);
}

Der Dienstvorgang verarbeitet die übermittelte Bestellung. OperationBehaviorAttribute wird auf den Dienstvorgang angewendet, um die automatische Eintragung in die Transaktion, die für den Empfang der Nachricht aus der Warteschlange verwendet wird, und die automatische Fertigstellung der Transaktion bei Abschluss des Dienstvorgangs festzulegen. Die Orders-Klasse kapselt die Auftragsverarbeitungsfunktion. In diesem Fall fügt sie die Bestellung einem Wörterbuch hinzu. Die Transaktion, in der der Dienstvorgang eingetragen wurde, steht den Vorgängen in der Orders-Klasse zur Verfügung.

Der Dienstvorgang verarbeitet die übermittelte Bestellung und meldet dem Client den Status der Bestellung.

public class OrderProcessorService : IOrderProcessor
{
    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public void SubmitPurchaseOrder(PurchaseOrder po, string reportOrderStatusTo)
    {
        Orders.Add(po);
        Console.WriteLine("Processing {0} ", po);
        Console.WriteLine("Sending back order status information");
        NetMsmqBinding msmqCallbackBinding = new NetMsmqBinding();
        msmqCallbackBinding.Security.Mode = NetMsmqSecurityMode.None;
        OrderStatusClient client = new OrderStatusClient(msmqCallbackBinding, new EndpointAddress(reportOrderStatusTo));
        // please note that the same transaction that is used to dequeue purchase order is used
        // to send back order status
        using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
        {
            client.OrderStatus(po.PONumber, po.Status);
            scope.Complete();
        }
    }

Die zu verwendende Clientbindung wird mithilfe einer Konfigurationsdatei festgelegt.

Der MSMQ-Warteschlangenname wird im appSettings-Abschnitt der Konfigurationsdatei angegeben. Der Endpunkt für den Dienst wird im Abschnitt "System.serviceModel" der Konfigurationsdatei definiert.

Tipp

Der Name der MSMQ-Warteschlange und die Endpunktadresse verwenden geringfügig abweichende Adressierungskonventionen. Im MSMQ-Warteschlangennamen wird ein Punkt (.) für den lokalen Computer verwendet, und in der Pfadangabe werden umgekehrte Schrägstriche als Trennzeichen verwendet. Die WCF-Endpunktadresse gibt ein net.msmq:-Schema an und verwendet "localhost" als lokalen Computer sowie Schrägstriche im Pfad. Um in einer Warteschlange zu lesen, die auf einem Remotecomputer gehostet wird, ersetzen Sie "." und "localhost" durch den Namen des Remotecomputers.

Um den Dienstcode in WAS zu hosten, wird eine .svc-Datei mit dem Namen der Klasse verwendet.

Die Datei "Service.svc" selbst enthält eine Direktive zur Erstellung von OrderProcessorService.

<%@ServiceHost language="c#" Debug="true" Service="Microsoft.ServiceModel.Samples.OrderProcessorService"%>

Die Datei "Service.svc" enthält darüber hinaus eine Assemblydirektive, um sicherzustellen, dass "System.Transactions.dll" geladen wird.

<%@Assembly name="System.Transactions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"%>

Der Client erstellt einen Geltungsbereich für die Transaktion. Die Kommunikation mit dem Dienst findet innerhalb des Geltungsbereichs der Transaktion statt, sodass diese in der Folge als unteilbare Einheit behandelt wird, in der alle Nachrichten entweder erfolgreich sind oder fehlschlagen. Für die Transaktion wird ein Commit ausgeführt, indem Complete im Geltungsbereich der Transaktion aufgerufen wird.

using (ServiceHost serviceHost = new ServiceHost(typeof(OrderStatusService)))
{
    // Open the ServiceHostBase to create listeners and start listening 
    // for order status messages.
    serviceHost.Open();

    // Create a proxy with given client endpoint configuration
    OrderProcessorClient client = new OrderProcessorClient();

    // Create the purchase order
    PurchaseOrder po = new PurchaseOrder();
    po.CustomerId = "somecustomer.com";
    po.PONumber = Guid.NewGuid().ToString();

    PurchaseOrderLineItem lineItem1 = new PurchaseOrderLineItem();
    lineItem1.ProductId = "Blue Widget";
    lineItem1.Quantity = 54;
    lineItem1.UnitCost = 29.99F;

    PurchaseOrderLineItem lineItem2 = new PurchaseOrderLineItem();
    lineItem2.ProductId = "Red Widget";
    lineItem2.Quantity = 890;
    lineItem2.UnitCost = 45.89F;

    po.orderLineItems = new PurchaseOrderLineItem[2];
    po.orderLineItems[0] = lineItem1;
    po.orderLineItems[1] = lineItem2;

    //Create a transaction scope.
    using (TransactionScope scope = new 
        TransactionScope(TransactionScopeOption.Required))
    {
        // Make a queued call to submit the purchase order
        client.SubmitPurchaseOrder(po, 
       "net.msmq://localhost/private/ServiceModelSamples/OrderStatus");
        // Complete the transaction.
        scope.Complete();
    }

    //Closing the client gracefully closes the connection and cleans up 
    //resources
    client.Close();

    Console.WriteLine();
    Console.WriteLine("Press <ENTER> to terminate client.");
    Console.ReadLine();

    // Close the ServiceHostBase to shutdown the service.
    serviceHost.Close();
    }

Der Clientcode implementiert den IOrderStatus-Vertrag, um den Auftragsstatus vom Dienst zu empfangen. In diesem Fall druckt er den Auftragsstatus aus.

[ServiceBehavior]
public class OrderStatusService : IOrderStatus
{
    [OperationBehavior(TransactionAutoComplete = true, 
                        TransactionScopeRequired = true)]
    public void OrderStatus(string poNumber, string status)
    {
        Console.WriteLine("Status of order {0}:{1} ", 
                                         poNumber , status);
    }
}

Die Auftragsstatuswarteschlange wird in der Main-Methode erstellt. Die Clientkonfiguration beinhaltet die Dienstkonfiguration für den Auftragsstatus, um den Auftragsstatusdienst zu hosten, wie in der folgenden Beispielkonfiguration dargestellt.

<appSettings>
    <!-- use appSetting to configure MSMQ queue name -->
    <add key="targetQueueName" value=".\private$\ServiceModelSamples/service.svc" />
    <add key="responseQueueName" value=".\private$\ServiceModelSamples/OrderStatus" />
  </appSettings>

<system.serviceModel>

    <services>
      <service 
         name="Microsoft.ServiceModel.Samples.OrderStatusService">
        <!-- Define NetMsmqEndpoint -->
        <endpoint address="net.msmq://localhost/private/ServiceModelSamples/OrderStatus"
                  binding="netMsmqBinding"
                  contract="Microsoft.ServiceModel.Samples.IOrderStatus" />
      </service>
    </services>

    <client>
      <!-- Define NetMsmqEndpoint -->
      <endpoint name="OrderProcessorEndpoint"
                address="net.msmq://localhost/private/ServiceModelSamples/service.svc" 
                binding="netMsmqBinding" 
                contract="Microsoft.ServiceModel.Samples.IOrderProcessor" />
    </client>

  </system.serviceModel>

Wenn Sie das Beispiel ausführen, werden die Client- und Dienstaktivitäten sowohl im Server- als auch im Clientkonsolenfenster angezeigt. Sie können sehen, wie der Server Nachrichten vom Client empfängt. Drücken Sie die EINGABETASTE in den einzelnen Konsolenfenstern, um den Server und den Client zu schließen.

Der Client zeigt die vom Server gesendeten Bestellstatusinformationen an.

Press <ENTER> to terminate client.
Status of order 70cf9d63-3dfa-4e69-81c2-23aa4478ebed :Pending

So richten Sie das Beispiel ein, erstellen es und führen es aus

  1. Stellen Sie sicher, dass Sie die Beispiele zum einmaligen Setupverfahren für Windows Communication Foundation ausgeführt haben. Außerdem müssen Sie die WCF-Aktivierungskomponenten für andere Protokolle als HTTP installieren:

    1. Aktivieren Sie über das Menü Start die Systemsteuerung.
    2. Wählen Sie Programme und dann Programme und Funktionen aus, oder wählen Sie in der klassischen Ansicht Programme und Funktionen aus.
    3. Klicken Sie auf Windows-Funktionen ein- oder ausschalten.
    4. Klicken Sie unter Features-Zusammenfassung auf Features hinzufügen.
    5. Erweitern Sie den Knoten Microsoft .NET Framework 3.0, und aktivieren Sie das Feature Windows Communication Foundation-Nicht-HTTP-Aktivierung.
  2. Zum Erstellen der C#- oder Visual Basic .NET-Version der Projektmappe folgen Sie den unter Erstellen der Windows Communication Foundation-Beispiele aufgeführten Anweisungen.

  3. Führen Sie den Client aus, indem Sie "client.exe" von einem Befehlsfenster ausführen. Auf diese Weise wird die Warteschlange erstellt und eine Nachricht an sie gesendet. Der Client verbleibt in der Ausführung, um das Ergebnis des Lesens der Nachricht durch den Dienst zu sehen.

  4. Der MSMQ-Aktivierungsdienst wird standardmäßig als Netzwerkdienst ausgeführt. Daher muss die Warteschlange, die zur Aktivierung der Anwendung verwendet wird, über Empfangs- und Einsehberechtigungen für den Netzwerkdienst verfügen. Diese können durch Verwendung von Message Queuing MMC hinzugefügt werden:

    1. Klicken Sie im Menü Start auf Ausführen, geben Sie Compmgmt.msc ein, und betätigen Sie die Eingabetaste.
    2. Erweitern Sie unter Dienste und AnwendungenMessage Queuing.
    3. Klicken Sie auf Private Warteschlangen.
    4. Klicken Sie mit der rechten Maustaste auf die Warteschlange (servicemodelsamples/Service.svc), und wählen Sie Eigenschaften aus.
    5. Klicken Sie auf der Registerkarte Sicherheit auf Hinzufügen, und weisen Sie dem Netzwerkdienst Einseh- und Empfangsberechtigungen zu.
  5. Konfigurieren Sie den Windows Process Activation Service (WAS), um die MSMQ-Aktivierung zu unterstützen.

    1. Führen Sie "Inetmgr.exe" aus.
    2. Um für die Standardwebsite die Kommunikation über das net.msmq-Protokoll zu aktivieren, müssen Sie eine neue Sitebindung hinzufügen. Führen Sie hierzu die Befehlsdatei "AddMsmqSiteBinding.cmd" aus dem Beispielverzeichnis aus.
  6. Falls noch nicht geschehen, stellen Sie sicher, dass der MSMQ-Aktivierungsdienst aktiviert ist. Klicken Sie im Menü Start auf Ausführen, und geben Sie Services.msc ein. Suchen Sie in der Liste der Dienste nach dem Net.Msmq-Listeneradapter. Klicken Sie mit der rechten Maustaste, und wählen Sie Eigenschaften aus. Legen Sie den Starttyp auf Automatisch fest, klicken Sie auf Übernehmen, und klicken Sie auf die Schaltfläche Start. Dieser Schritt muss nur einmal vor der ersten Verwendung des Net.Msmq-Listeneradapterdiensts durchgeführt werden.

  7. Wenn Sie das Beispiel in einer Konfiguration mit einem Computer oder computerübergreifend ausführen möchten, folgen Sie den unter Durchführen der Windows Communication Foundation-Beispiele aufgeführten Anweisungen. Ändern Sie zusätzlich den Code auf dem Client, der die Bestellung einsendet, um den Computernamen im URI der Warteschlange beim Einsenden der Bestellung wiederzugeben. Verwenden Sie folgenden Code:

    client.SubmitPurchaseOrder(po, "net.msmq://localhost/private/ServiceModelSamples/OrderStatus");
    

Standardmäßig wird mit der netMsmqBinding-Bindung die Transportsicherheit aktiviert. Der Typ der Transportsicherheit wird durch zwei Eigenschaften festgelegt: MsmqAuthenticationMode und MsmqProtectionLevel. Standardmäßig wird der Authentifizierungsmodus auf Windows festgelegt, und die Schutzebene wird auf Sign gesetzt. Damit MSMQ das Authentifizierungs- und Signierungsfeature bereitstellt, muss es Teil einer Domäne sein. Wenn Sie dieses Beispiel auf einem Computer ausführen, der nicht Teil einer Domäne ist, wird folgende Fehlermeldung ausgegeben: "Das interne Message Queuing-Zertifikat für diesen Benutzer ist nicht vorhanden."

So führen Sie das Beispiel auf einem Computer aus, der mit einer Arbeitsgruppe verbunden ist

  1. Wenn Ihr Computer nicht zu einer Domäne gehört, deaktivieren Sie die Transportsicherheit, indem Sie den Authentifizierungsmodus und die Schutzebene auf "None" festlegen, wie in der folgenden Beispielkonfiguration gezeigt.

    <bindings>
        <netMsmqBinding>
            <binding configurationName="TransactedBinding">
                <security mode="None"/>
            </binding>
        </netMsmqBinding>
    </bindings>
    
  2. Ändern Sie die Konfiguration sowohl auf dem Server als auch auf dem Client, bevor Sie das Beispiel ausführen.

    Tipp

    Das Festlegen von security mode auf None entspricht dem Festlegen von MsmqAuthenticationMode, MsmqProtectionLevel und der Message-Sicherheit auf None.

  3. Um die Aktivierung auf einem Computer zu ermöglichen, der mit einer Arbeitsgruppe verbunden ist, müssen sowohl der Aktivierungsdienst als auch der Workerprozess mit einem spezifischen Benutzerkonto ausgeführt werden (das gleiche Konto für beide), und die Warteschlange muss über ACLs für das spezifische Benutzerkonto verfügen.

    So ändern Sie die Identität, unter der der Workerprozess ausgeführt wird:

    1. Führen Sie "Inetmgr.exe" aus.
    2. Klicken Sie unter Anwendungspools mit der rechten Maustaste auf AppPool (üblicherweise DefaultAppPool), und wählen Sie Set Application Pool Defaults… (Standards für Anwendungspools festlegen) aus.
    3. Ändern Sie die Identitätseigenschaften, um das bestimmte Benutzerkonto zu verwenden.

    So ändern Sie die Identität, unter der der Aktivierungsdienst ausgeführt wird:

    1. Führen Sie "Services.msc" aus.
    2. Klicken Sie mit der rechten Maustaste auf Net.MsmqListener-Adapter, und wählen Sie Eigenschaften aus.
  4. Ändern Sie das Konto auf der Registerkarte LogOn.

  5. In der Arbeitsgruppe muss der Dienst auch mit einem uneingeschränkten Token ausgeführt werden. Um dies zu erreichen, führen Sie im Befehlsfenster Folgendes aus:

    sc sidtype netmsmqactivator unrestricted
    

Send comments about this topic to Microsoft.
© 2007 Microsoft Corporation. All rights reserved.