Sdílet prostřednictvím


Relace a fronty

Ukázka relace ukazuje, jak odesílat a přijímat sadu souvisejících zpráv ve frontě komunikace přes přenos služby Řízení front zpráv (MSMQ). Tato ukázka používá netMsmqBinding vazbu. Služba je konzolová aplikace v místním prostředí, která umožňuje sledovat službu, která přijímá zprávy ve frontě.

Poznámka:

Postup nastavení a pokyny k sestavení pro tuto ukázku najdete na konci tohoto tématu.

Ve frontě komunikace klient komunikuje se službou pomocí fronty. Přesněji řečeno, klient odesílá zprávy do fronty. Služba přijímá zprávy z fronty. Služba a klient proto nemusí být spuštěna ve stejnou dobu, aby komunikovaly pomocí fronty.

Někdy klient odešle sadu zpráv, které spolu vzájemně souvisejí ve skupině. Pokud musí být zprávy zpracovány společně nebo v zadaném pořadí, lze frontu použít k jejich seskupování ke zpracování jednou přijímající aplikací. To je zvlášť důležité, pokud je na skupině serverů několik přijímajících aplikací a je nutné zajistit, aby stejná přijímající aplikace zpracovávala skupinu zpráv. Relace ve frontě jsou mechanismus, který slouží k odesílání a přijímání související sady zpráv, které se musí zpracovat najednou. Relace ve frontě vyžadují k zobrazení tohoto vzoru transakci.

V ukázce klient odešle do služby řadu zpráv v rámci relace v rámci rozsahu jedné transakce.

Kontrakt služby je IOrderTaker, který definuje jednosměrnou službu, která je vhodná pro použití s frontami. Použité SessionMode ve smlouvě zobrazené v následujícím vzorovém kódu označuje, že zprávy jsou součástí relace.

[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();
}

Služba definuje operace služby takovým způsobem, že první operace vypisuje do transakce, ale automaticky nedokon čte transakci. Následné operace se také začtou do stejné transakce, ale automaticky se nedokonují. Poslední operace v relaci automaticky dokončí transakci. Proto se stejná transakce používá pro několik operací vyvolání ve smlouvě služby. Pokud některá z operací vyvolá výjimku, transakce se vrátí zpět a relace se vrátí do fronty. Po úspěšném dokončení poslední operace se transakce potvrdí. Služba používá PerSession jako InstanceContextMode příjem všech zpráv v relaci ve stejné instanci služby.

[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());
    }
}

Služba je hostovaná v místním prostředí. Při použití přenosu MSMQ je nutné předem vytvořit použitou frontu. Můžete to provést ručně nebo prostřednictvím kódu. V této ukázce obsahuje System.Messaging služba kód pro kontrolu existence fronty a v případě potřeby ji vytvoří. Název fronty se načte z konfiguračního souboru pomocí AppSettings třídy.

// 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();
    }
}

Název fronty MSMQ se zadává v části aplikace Nastavení konfiguračního souboru. Koncový bod pro službu je definován v části system.serviceModel konfiguračního souboru a určuje netMsmqBinding vazbu.

<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>

Klient vytvoří obor transakce. Všechny zprávy v relaci se odesílají do fronty v rámci oboru transakce, což způsobí, že se bude považovat za atomické jednotky, kde všechny zprávy proběhnou úspěšně nebo selžou. Transakce je potvrzena voláním 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();
}

Poznámka:

Před potvrzením transakce můžete použít pouze jednu transakci pro všechny zprávy v relaci a všechny zprávy v relaci musí být odeslány. Zavření klienta relaci zavře. Proto musí být klient uzavřen před dokončením transakce odeslat všechny zprávy v relaci do fronty.

Při spuštění ukázky se aktivity klienta a služeb zobrazí v oknech služby i konzoly klienta. Můžete vidět, že služba přijímá zprávy od klienta. Stisknutím klávesy ENTER v každém okně konzoly vypnete službu a klienta. Vzhledem k tomu, že se používá řízení front, klient a služba nemusí být ve stejnou dobu spuštěné a spuštěné. Klienta můžete spustit, vypnout ho a pak spustit službu a stále přijímat její zprávy.

V klientovi.

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

Press <ENTER> to terminate client.

Ve službě.

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

Nastavení, sestavení a spuštění ukázky

  1. Ujistěte se, že jste pro ukázky windows Communication Foundation provedli jednorázovou instalační proceduru.

  2. Pokud chcete sestavit edici C#, C++ nebo Visual Basic .NET řešení, postupujte podle pokynů v části Sestavení ukázek windows Communication Foundation.

  3. Pokud chcete spustit ukázku v konfiguraci s jedním nebo více počítači, postupujte podle pokynů v části Spuštění ukázek windows Communication Foundation.

Ve výchozím nastavení NetMsmqBindingje povolené zabezpečení přenosu. Existují dvě relevantní vlastnosti zabezpečení přenosu MSMQ a MsmqAuthenticationModeMsmqProtectionLevel. ve výchozím nastavení je režim ověřování nastaven Windows na úroveň Signochrany . Aby služba MSMQ poskytovala funkci ověřování a podepisování, musí být součástí domény a musí být nainstalovaná možnost integrace služby Active Directory pro MSMQ. Pokud tuto ukázku spustíte na počítači, který nesplňuje tato kritéria, zobrazí se chyba.

Spuštění ukázky na počítači připojeném k pracovní skupině

  1. Pokud váš počítač není součástí domény nebo nemá nainstalovanou integraci služby Active Directory, vypněte zabezpečení přenosu nastavením režimu ověřování a úrovně ochrany tak, jak None je znázorněno v následující ukázkové konfiguraci.

    <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. Před spuštěním ukázky nezapomeňte změnit konfiguraci na serveru i klientovi.

    Poznámka:

    Nastavení režimu zabezpečení tak, aby None odpovídalo nastavení MsmqAuthenticationMode, MsmqProtectionLevela Message zabezpečení na None.