Sdílet prostřednictvím


Korelace zpráv

Ukázka MessageCorrelation ukazuje, jak může aplikace služby Řízení front zpráv (MSMQ) odeslat zprávu MSMQ službě Windows Communication Foundation (WCF) a jak lze zprávy korelovat mezi odesílateli a přijímacími aplikacemi ve scénáři požadavku a odpovědi. Tato ukázka používá vazbu msmqIntegrationBinding. Služba v tomto případě je konzolová aplikace v místním prostředí, která umožňuje sledovat službu, která přijímá zprávy ve frontě. k

Služba zpracuje zprávu přijatou od odesílatele a odešle zprávu s odpovědí zpět odesílateli. Odesílatel koreluje odpověď, kterou přijala, na žádost, kterou původně odeslal. Vlastnosti zprávy MessageID a CorrelationID se používají k provázání požadavků a odpovědí.

Kontrakt IOrderProcessor služby definuje jednosměrnou operaci služby, která je vhodná pro použití s frontami. Zpráva MSMQ nemá záhlaví akce, takže není možné mapovat různé zprávy MSMQ na kontrakty operací automaticky. V tomto případě proto může existovat pouze jeden kontrakt operace. Pokud chcete definovat více kontraktů operací ve službě, musí aplikace poskytnout informace o tom, jaká hlavička ve zprávě MSMQ (například popisek nebo ID korelace) se dá použít k rozhodnutí, který kontrakt operace se má odeslat.

Zpráva MSMQ také neobsahuje informace o tom, které hlavičky jsou mapovány na různé parametry operačního kontraktu. Proto může být v kontraktu operace pouze jeden parametr. Parametr je typu MsmqMessage<T>, který obsahuje základní zprávu MSMQ. Typ "T" ve MsmqMessage<T> třídě představuje data, která jsou serializována do textu zprávy MSMQ. V této ukázce je typ PurchaseOrder serializován do těla zprávy MSMQ.

[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
[ServiceKnownType(typeof(PurchaseOrder))]
public interface IOrderProcessor
{
    [OperationContract(IsOneWay = true, Action = "*")]
    void SubmitPurchaseOrder(MsmqMessage<PurchaseOrder> msg);
}

Operace služby zpracuje nákupní objednávku a zobrazí obsah nákupní objednávky a její stav v okně konzoly služby. Nakonfiguruje OperationBehaviorAttribute operaci tak, aby se připojila k transakci s frontou a aby transakci označila jako dokončenou po dokončení operace. Obsahuje PurchaseOrder podrobnosti objednávky, které musí služba zpracovat.

// Service class that implements the service contract.
public class OrderProcessorService : IOrderProcessor
{
   [OperationBehavior(TransactionScopeRequired = true,
          TransactionAutoComplete = true)]
   public void SubmitPurchaseOrder(MsmqMessage<PurchaseOrder> ordermsg)
   {
       PurchaseOrder po = (PurchaseOrder)ordermsg.Body;
       Random statusIndexer = new Random();
       po.Status = PurchaseOrder.OrderStates[statusIndexer.Next(3)];
       Console.WriteLine("Processing {0} ", po);
       //Send a response to the client that the order has been received
       // and is pending fulfillment.
       SendResponse(ordermsg);
    }

    private void SendResponse(MsmqMessage<PurchaseOrder> ordermsg)
    {
        OrderResponseClient client = new OrderResponseClient("OrderResponseEndpoint");

        //Set the correlation ID such that the client can correlate the response to the order.
        MsmqMessage<PurchaseOrder> orderResponseMsg = new MsmqMessage<PurchaseOrder>(ordermsg.Body);
        orderResponseMsg.CorrelationId = ordermsg.Id;
        using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
        {
            client.SendOrderResponse(orderResponseMsg);
            scope.Complete();
        }

        client.Close();
    }
}

Služba používá vlastního klienta OrderResponseClient k odeslání zprávy MSMQ do fronty. Vzhledem k tomu, že aplikace, která přijímá a zpracovává zprávu, je aplikace MSMQ, a nikoli aplikace WCF, neexistuje mezi těmito dvěma aplikacemi implicitní kontrakt služby. Proto nemůžeme vytvořit proxy server pomocí nástroje Svcutil.exe v tomto scénáři.

Vlastní proxy server je v podstatě stejný pro všechny aplikace WCF, které používají msmqIntegrationBinding vazbu k odesílání zpráv. Na rozdíl od jiných proxy serverů nezahrnuje celou řadu operací služby. Jedná se pouze o operaci odeslání zprávy.

[System.ServiceModel.ServiceContractAttribute(Namespace = "http://Microsoft.ServiceModel.Samples")]
public interface IOrderResponse
{

    [System.ServiceModel.OperationContractAttribute(IsOneWay = true, Action = "*")]
    void SendOrderResponse(MsmqMessage<PurchaseOrder> msg);
}

public partial class OrderResponseClient : System.ServiceModel.ClientBase<IOrderResponse>, IOrderResponse
{

    public OrderResponseClient()
    { }

    public OrderResponseClient(string configurationName)
        : base(configurationName)
    { }

    public OrderResponseClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress address)
        : base(binding, address)
    { }

    public void SendOrderResponse(MsmqMessage<PurchaseOrder> msg)
    {
        base.Channel.SendOrderResponse(msg);
    }
}

Služba je hostovaná uživatelem. Při použití přenosu integrace MSMQ je nutné předem vytvořit frontu, která se bude používat. 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, který zkontroluje existenci fronty a v případě potřeby ji vytvoří. Název fronty se načte z konfiguračního souboru.

public static void Main()
{
       // Get the MSMQ queue name from application settings in configuration.
      string queueName =
                ConfigurationManager.AppSettings["orderQueueName"];
      // Create the transacted MSMQ queue if necessary.
      if (!MessageQueue.Exists(queueName))
                MessageQueue.Create(queueName, true);
     // Create a ServiceHost for the OrderProcessorService type.
     using (ServiceHost serviceHost = new
                   ServiceHost(typeof(OrderProcessorService)))
     {
            serviceHost.Open();
            // The service can now be accessed.
            Console.WriteLine("The service is ready.");
            Console.WriteLine("Press <ENTER> to terminate service.");
            Console.ReadLine();
            // Close the ServiceHost to shutdown the service.
            serviceHost.Close();
      }
}

Fronta MSMQ, do které se odesílají požadavky na objednávku, je specifikována v sekci appSettings konfiguračního souboru. Koncové body klienta a služby jsou definovány v části system.serviceModel konfiguračního souboru. Obě určují vazbu msmqIntegrationBinding.

<appSettings>
  <add key="orderQueueName" value=".\private$\Orders" />
</appSettings>

<system.serviceModel>
  <client>
    <endpoint    name="OrderResponseEndpoint"
              address="msmq.formatname:DIRECT=OS:.\private$\OrderResponse"
              binding="msmqIntegrationBinding"
              bindingConfiguration="OrderProcessorBinding"
              contract="Microsoft.ServiceModel.Samples.IOrderResponse">
    </endpoint>
  </client>

  <services>
    <service
      name="Microsoft.ServiceModel.Samples.OrderProcessorService">
      <endpoint address="msmq.formatname:DIRECT=OS:.\private$\Orders"
                            binding="msmqIntegrationBinding"
                bindingConfiguration="OrderProcessorBinding"
                contract="Microsoft.ServiceModel.Samples.IOrderProcessor">
      </endpoint>
    </service>
  </services>

  <bindings>
    <msmqIntegrationBinding>
      <binding name="OrderProcessorBinding" >
        <security mode="None" />
      </binding>
    </msmqIntegrationBinding>
  </bindings>

</system.serviceModel>

Klientská aplikace používá System.Messaging k odeslání zprávy, která je trvalá a transakční, do fronty. Text zprávy obsahuje nákupní objednávku.

static void PlaceOrder()
{
    //Connect to the queue
    MessageQueue orderQueue =
            new MessageQueue(
                    ConfigurationManager.AppSettings["orderQueueName"])
    // 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;

    Message msg = new Message();
    msg.UseDeadLetterQueue = true;
    msg.Body = po;

    //Create a transaction scope.
    using (TransactionScope scope = new
     TransactionScope(TransactionScopeOption.Required))
    {
        // Submit the purchase order.
        orderQueue.Send(msg, MessageQueueTransactionType.Automatic);
        // Complete the transaction.
        scope.Complete();
    }
    //Save the messageID for order response correlation.
    orderMessageID = msg.Id;
    Console.WriteLine("Placed the order, waiting for response...");
}

Fronta MSMQ, z které se přijímají odpovědi na objednávky, je v konfiguračním souboru uvedena v části appSettings, jak je znázorněno v následující ukázkové konfiguraci.

Poznámka:

Název fronty používá tečku (.) pro místní počítač a zpětná lomítka jako oddělovače ve své cestě. Adresa koncového bodu WCF určuje schéma msmq.formatname a pro místní počítač používá "localhost". Správně vytvořený název formátu následuje za msmq.formatname v URI podle pokynů MSMQ.

<appSettings>
    <add key=" orderResponseQueueName" value=".\private$\Orders" />
</appSettings>

Klientská aplikace uloží messageID zprávu žádosti o objednávku, kterou odešle službě, a čeká na odpověď ze služby. Jakmile odpověď do fronty dorazí, klient ji koreluje se zprávou objednávky, kterou odeslal pomocí correlationID vlastnosti zprávy, která obsahuje messageID zprávu objednávky, kterou klient původně odeslal do služby.

static void DisplayOrderStatus()
{
    MessageQueue orderResponseQueue = new
     MessageQueue(ConfigurationManager.AppSettings
                  ["orderResponseQueueName"]);
    //Create a transaction scope.
    bool responseReceived = false;
    orderResponseQueue.MessageReadPropertyFilter.CorrelationId = true;
    while (!responseReceived)
    {
       Message responseMsg;
       using (TransactionScope scope2 = new
         TransactionScope(TransactionScopeOption.Required))
       {
          //Receive the Order Response message.
          responseMsg =
              orderResponseQueue.Receive
                   (MessageQueueTransactionType.Automatic);
          scope2.Complete();
     }
     responseMsg.Formatter = new
     System.Messaging.XmlMessageFormatter(new Type[] {
         typeof(PurchaseOrder) });
     PurchaseOrder responsepo = (PurchaseOrder)responseMsg.Body;
    //Check if the response is for the order placed.
    if (orderMessageID == responseMsg.CorrelationId)
    {
       responseReceived = true;
       Console.WriteLine("Status of current Order: OrderID-{0},Order
            Status-{1}", responsepo.PONumber, responsepo.Status);
    }
    else
    {
       Console.WriteLine("Status of previous Order: OrderID-{0},Order
            Status-{1}", responsepo.PONumber, responsepo.Status);
    }
  }
}

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 a odesílá odpověď zpět klientovi. Klient zobrazí odpověď přijatou ze služby. Stisknutím klávesy ENTER v každém okně konzoly vypnete službu a klienta.

Poznámka:

Tato ukázka vyžaduje instalaci služby Řízení front zpráv (MSMQ). Pokyny k instalaci MSMQ najdete v části Viz také.

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

  1. Ujistěte se, že jste provedli instalační proceduru One-Time pro ukázky Windows Communication Foundation.

  2. Pokud je služba spuštěná jako první, zkontroluje, jestli je fronta k dispozici. Pokud fronta není k dispozici, služba ji vytvoří. Službu můžete nejprve spustit, abyste vytvořili frontu, nebo ji můžete vytvořit prostřednictvím Správce front MSMQ. Podle těchto kroků vytvořte frontu v systému Windows 2008.

    1. Otevřete Správce serveru v sadě Visual Studio 2012.

    2. Rozbalte panel Funkce.

    3. Klikněte pravým tlačítkem na Soukromé fronty zpráva vyberte Nová, soukromá fronta.

    4. Zaškrtněte políčko Transakční.

    5. Jako název nové fronty zadejte ServiceModelSamplesTransacted.

  3. Pokud chcete sestavit verzi C# nebo Visual Basic .NET řešení, postupujte podle pokynů v Sestavení ukázek Windows Communication Foundation.

  4. Pokud chcete spustit ukázku v konfiguraci s jedním počítačem, postupujte podle pokynů v Spuštění ukázek Windows Communication Foundation.

Spusťte ukázkový příklad na více počítačích

  1. Zkopírujte soubory programu služby ze složky \service\bin\ ve složce specifické pro jazyk do počítače služby.

  2. Zkopírujte soubory klientského programu ze složky \client\bin\ ve složce specifické pro jazyk do klientského počítače.

  3. V souboru Client.exe.config změňte pořadíQueueName tak, aby místo "."zadal název počítače služby.

  4. V souboru Service.exe.config změňte adresu koncového bodu klienta tak, aby místo "."zadal název klientského počítače.

  5. Na počítači služby spusťte Service.exe z příkazového řádku.

  6. Na klientském počítači spusťte Client.exe z příkazového řádku.

Viz také