Dela via


Sessioner och köer

Sessionsexemplet visar hur du skickar och tar emot en uppsättning relaterade meddelanden i köad kommunikation via MSMQ-transporten (Message Queuing). Det här exemplet använder bindningen netMsmqBinding . Tjänsten är ett konsolprogram med egen värd som gör att du kan observera att tjänsten tar emot köade meddelanden.

Kommentar

Installationsproceduren och bygginstruktionerna för det här exemplet finns i slutet av det här avsnittet.

I kökommunikation kommunicerar klienten till tjänsten med hjälp av en kö. Mer exakt skickar klienten meddelanden till en kö. Tjänsten tar emot meddelanden från kön. Tjänsten och klienten behöver därför inte köras samtidigt för att kommunicera med en kö.

Ibland skickar en klient en uppsättning meddelanden som är relaterade till varandra i en grupp. När meddelanden måste bearbetas tillsammans eller i en angiven ordning kan en kö användas för att gruppera dem, för bearbetning av ett enda mottagande program. Detta är särskilt viktigt när det finns flera mottagande program på en grupp servrar och det är nödvändigt att se till att en grupp meddelanden bearbetas av samma mottagande program. Köade sessioner är en mekanism som används för att skicka och ta emot en relaterad uppsättning meddelanden som måste bearbetas samtidigt. Köade sessioner kräver en transaktion för att visa det här mönstret.

I exemplet skickar klienten ett antal meddelanden till tjänsten som en del av en session inom omfånget för en enskild transaktion.

Tjänstkontraktet är IOrderTaker, som definierar en enkelriktad tjänst som är lämplig för användning med köer. Det SessionMode som används i kontraktet som visas i följande exempelkod anger att meddelandena ingår i sessionen.

[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples", SessionMode=SessionMode.Required)]
public interface IOrderTaker
{
    [OperationContract(IsOneWay = true)]
    void OpenPurchaseOrder(string customerId);

    [OperationContract(IsOneWay = true)]
    void AddProductLineItem(string productId, int quantity);

    [OperationContract(IsOneWay = true)]
    void EndPurchaseOrder();
}

Tjänsten definierar tjänståtgärder på ett sådant sätt att den första åtgärden listas i en transaktion men inte slutför transaktionen automatiskt. Efterföljande åtgärder listas också i samma transaktion men slutförs inte automatiskt. Den sista åtgärden i sessionen slutför automatiskt transaktionen. Därför används samma transaktion för flera åtgärdsanrop i tjänstkontraktet. Om någon av åtgärderna utlöser ett undantag återställs transaktionen och sessionen sätts tillbaka i kön. När den senaste åtgärden har slutförts checkas transaktionen in. Tjänsten använder PerSession som InstanceContextMode för att ta emot alla meddelanden i en session på samma instans av tjänsten.

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class OrderTakerService : IOrderTaker
{
    PurchaseOrder po;

    [OperationBehavior(TransactionScopeRequired = true,
                                 TransactionAutoComplete = false)]
    public void OpenPurchaseOrder(string customerId)
    {
        Console.WriteLine("Creating purchase order");
        po = new PurchaseOrder(customerId);
    }

    [OperationBehavior(TransactionScopeRequired = true,
                                  TransactionAutoComplete = false)]
    public void AddProductLineItem(string productId, int quantity)
    {
        po.AddProductLineItem(productId, quantity);
        Console.WriteLine("Product " + productId + " quantity " +
                            quantity + " added to purchase order");
    }

    [OperationBehavior(TransactionScopeRequired = true,
                                  TransactionAutoComplete = true)]
    public void EndPurchaseOrder()
    {
       Console.WriteLine("Purchase Order Completed");
       Console.WriteLine();
       Console.WriteLine(po.ToString());
    }
}

Tjänsten är lokalt installerad. När du använder MSMQ-transporten måste den kö som används skapas i förväg. Detta kan göras manuellt eller via kod. I det här exemplet innehåller System.Messaging tjänsten kod för att kontrollera om kön finns och skapar den om det behövs. Könamnet läss från konfigurationsfilen med hjälp av AppSettings klassen .

// Host the service within this EXE console application.
public static void Main()
{
    // Get MSMQ queue name from app settings in configuration.
    string queueName = ConfigurationManager.AppSettings["queueName"];

    // Create the transacted MSMQ queue if necessary.
    if (!MessageQueue.Exists(queueName))
        MessageQueue.Create(queueName, true);

    // Create a ServiceHost for the OrderTakerService type.
    using (ServiceHost serviceHost = new ServiceHost(typeof(OrderTakerService)))
    {
        // Open the ServiceHost to create listeners and start listening for messages.
        serviceHost.Open();

        // The service can now be accessed.
        Console.WriteLine("The service is ready.");
        Console.WriteLine("Press <ENTER> to terminate service.");
        Console.WriteLine();
        Console.ReadLine();

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

MSMQ-könamnet anges i en app Inställningar avsnitt i konfigurationsfilen. Slutpunkten för tjänsten definieras i avsnittet system.serviceModel i konfigurationsfilen och anger bindningen netMsmqBinding .

<appSettings>
  <!-- Use appSetting to configure MSMQ queue name. -->
  <add key="queueName" value=".\private$\ServiceModelSamplesSession" />
</appSettings>

<system.serviceModel>
  <services>
    <service name="Microsoft.ServiceModel.Samples.OrderTakerService"
        behaviorConfiguration="CalculatorServiceBehavior">
      ...
      <!-- Define NetMsmqEndpoint -->
      <endpoint address="net.msmq://localhost/private/ServiceModelSamplesSession"
                binding="netMsmqBinding"
                contract="Microsoft.ServiceModel.Samples.IOrderTaker" />
      ...
    </service>
  </services>
  ...
</system.serviceModel>

Klienten skapar ett transaktionsomfång. Alla meddelanden i sessionen skickas till kön inom transaktionsomfånget, vilket gör att det behandlas som en atomisk enhet där alla meddelanden lyckas eller misslyckas. Transaktionen genomförs genom att anropa Complete.

//Create a transaction scope.
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
{
    // Create a client with given client endpoint configuration.
    OrderTakerClient client = new OrderTakerClient("OrderTakerEndpoint");
    // Open a purchase order.
    client.OpenPurchaseOrder("somecustomer.com");
    Console.WriteLine("Purchase Order created");

    // Add product line items.
    Console.WriteLine("Adding 10 quantities of blue widget");
    client.AddProductLineItem("Blue Widget", 10);

    Console.WriteLine("Adding 23 quantities of red widget");
    client.AddProductLineItem("Red Widget", 23);

    // Close the purchase order.
    Console.WriteLine("Closing the purchase order");
    client.EndPurchaseOrder();

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

    // Complete the transaction.
    scope.Complete();
}

Kommentar

Du kan bara använda en enda transaktion för alla meddelanden i sessionen och alla meddelanden i sessionen måste skickas innan transaktionen genomförs. När klienten stängs stängs sessionen. Därför måste klienten stängas innan transaktionen slutförs för att skicka alla meddelanden i sessionen till kön.

När du kör exemplet visas klient- och tjänstaktiviteterna i både tjänst- och klientkonsolfönstren. Du kan se att tjänsten tar emot meddelanden från klienten. Tryck på RETUR i varje konsolfönster för att stänga av tjänsten och klienten. Eftersom köer används behöver klienten och tjänsten inte vara igång samtidigt. Du kan köra klienten, stänga av den och sedan starta tjänsten och fortfarande ta emot dess meddelanden.

På klienten.

Purchase Order created
Adding 10 quantities of blue widget
Adding 23 quantities of red widget
Closing the purchase order

Press <ENTER> to terminate client.

På tjänsten.

The service is ready.
Press <ENTER> to terminate service.

Creating purchase order
Product Blue Widget quantity 10 added to purchase order
Product Red Widget quantity 23 added to purchase order
Purchase Order Completed

Purchase Order: 7c86fef0-2306-4c51-80e6-bcabcc1a6e5e
        Customer: somecustomer.com
        OrderDetails
                Order LineItem: 10 of Blue Widget @unit price: $2985
                Order LineItem: 23 of Red Widget @unit price: $156
        Total cost of this order: $33438
        Order status: Pending

Konfigurera, skapa och köra exemplet

  1. Kontrollera att du har utfört engångsinstallationsproceduren för Windows Communication Foundation-exempel.

  2. Om du vill skapa C#,C++- eller Visual Basic .NET-versionen av lösningen följer du anvisningarna i Skapa Windows Communication Foundation-exempel.

  3. Om du vill köra exemplet i en konfiguration med en eller flera datorer följer du anvisningarna i Köra Windows Communication Foundation-exempel.

Som standard NetMsmqBindingär transportsäkerheten aktiverad. Det finns två relevanta egenskaper för MSMQ-transportsäkerhet, nämligen, MsmqAuthenticationMode och.MsmqProtectionLevelsom standard är autentiseringsläget inställt på Windows och skyddsnivån är inställd på Sign. För att MSMQ ska kunna tillhandahålla autentiserings- och signeringsfunktionen måste den vara en del av en domän och active directory-integreringsalternativet för MSMQ måste vara installerat. Om du kör det här exemplet på en dator som inte uppfyller dessa kriterier får du ett fel.

Kör exemplet på en dator som är ansluten till en arbetsgrupp

  1. Om datorn inte är en del av en domän eller inte har active directory-integrering installerad inaktiverar du transportsäkerheten genom att ställa in autentiseringsläget och skyddsnivån på None enligt följande exempelkonfiguration.

    <system.serviceModel>
      <services>
        <service name="Microsoft.ServiceModel.Samples.OrderTakerService"
                 behaviorConfiguration="OrderTakerServiceBehavior">
          <host>
            <baseAddresses>
              <add baseAddress=
             "http://localhost:8000/ServiceModelSamples/service"/>
            </baseAddresses>
          </host>
          <!-- Define NetMsmqEndpoint -->
          <endpoint
              address=
            "net.msmq://localhost/private/ServiceModelSamplesSession"
              binding="netMsmqBinding"
              bindingConfiguration="Binding1"
           contract="Microsoft.ServiceModel.Samples.IOrderTaker" />
          <!-- The mex endpoint is exposed at-->
          <!--http://localhost:8000/ServiceModelSamples/service/mex. -->
          <endpoint address="mex"
                    binding="mexHttpBinding"
                    contract="IMetadataExchange" />
        </service>
      </services>
    
      <bindings>
        <netMsmqBinding>
          <binding name="Binding1">
            <security mode="None" />
          </binding>
        </netMsmqBinding>
      </bindings>
    
        <behaviors>
          <serviceBehaviors>
            <behavior name="OrderTakerServiceBehavior">
              <serviceMetadata httpGetEnabled="True"/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
    
      </system.serviceModel>
    
  2. Se till att du ändrar konfigurationen på både servern och klienten innan du kör exemplet.

    Kommentar

    Att ställa in säkerhetsläge på None motsvarar inställningen MsmqAuthenticationMode, MsmqProtectionLeveloch Message säkerhet till None.