Sdílet prostřednictvím


Fronty nedoručených zpráv

Ukázka DeadLetter ukazuje, jak zpracovávat a zpracovávat zprávy, které selhaly doručení. Je založená na ukázce transacted MSMQ Binding . 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.

Poznámka:

Tato ukázka demonstruje každou frontu nedoručených zpráv aplikace, která je k dispozici pouze v systému Windows Vista. Ukázku lze upravit tak, aby používala výchozí systémové fronty pro MSMQ 3.0 v systémech Windows Server 2003 a Windows XP.

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.

Vzhledem k tomu, že komunikace ve frontě může zahrnovat určitou míru nečinnosti, můžete ke zprávě přidružit hodnotu time-to-live, abyste zajistili, že se zpráva nedoručí do aplikace, pokud uplynula čas. Existují také případy, kdy musí být aplikace informována, jestli zpráva selhala. Ve všech těchto případech, například když vypršela platnost zprávy typu time-to-live nebo zpráva selhala, zpráva se vloží do fronty nedoručených zpráv. Odesílající aplikace pak může číst zprávy ve frontě nedoručených zpráv a provádět opravné akce v rozsahu od žádné akce až po opravu důvodů neúspěšného doručení a opětovného odeslání zprávy.

Fronta nedoručených zpráv ve vazbě NetMsmqBinding je vyjádřena následujícími vlastnostmi:

  • DeadLetterQueue vlastnost pro vyjádření typu fronty nedoručených zpráv vyžadovaných klientem. Tento výčet má následující hodnoty:

  • None: Klient nevyžaduje žádnou frontu nedoručených zpráv.

  • System: Fronta nedoručených zpráv systému se používá k ukládání mrtvých zpráv. Fronta nedoručených zpráv systému je sdílena všemi aplikacemi spuštěnými v počítači.

  • Custom: Vlastní fronta nedoručených zpráv zadaná pomocí CustomDeadLetterQueue vlastnosti se používá k ukládání mrtvých zpráv. Tato funkce je k dispozici pouze v systému Windows Vista. To se používá, když aplikace musí místo sdílení s jinými aplikacemi spuštěnými na stejném počítači používat vlastní frontu nedoručených zpráv.

  • CustomDeadLetterQueue pro vyjádření konkrétní fronty, která se má použít jako fronta nedoručených zpráv. Tato možnost je k dispozici pouze v systému Windows Vista.

V této ukázce klient odešle službě dávku zpráv z rozsahu transakce a určuje libovolně nízkou hodnotu pro tyto zprávy "time-to-live" (přibližně 2 sekundy). Klient také určuje vlastní frontu nedoručených zpráv, která se má použít k zařazení zpráv, jejichž platnost vypršela.

Klientská aplikace může číst zprávy ve frontě nedoručených zpráv a buď zkusit zprávu odeslat znovu, nebo opravit chybu, která způsobila umístění původní zprávy do fronty nedoručených zpráv a odeslání zprávy. V ukázce zobrazí klient chybovou zprávu.

Kontrakt služby je , jak je IOrderProcessorznázorněno v následujícím vzorovém kódu.

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

Kód služby v ukázce je kód transacted MSMQ Binding.

Komunikace se službou probíhá v rámci transakce. Služba čte zprávy z fronty, provede operaci a pak zobrazí výsledky operace. Aplikace také vytvoří frontu nedoručených zpráv pro zprávy s nedoručenou zprávou.

//The service contract is defined in generatedClient.cs, generated from the service by the svcutil tool.

//Client implementation code.
class Client
{
    static void Main()
    {
        // Get MSMQ queue name from app settings in configuration
        string deadLetterQueueName = ConfigurationManager.AppSettings["deadLetterQueueName"];

        // Create the transacted MSMQ queue for storing dead message if necessary.
        if (!MessageQueue.Exists(deadLetterQueueName))
            MessageQueue.Create(deadLetterQueueName, true);

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

        // 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);
            // Complete the transaction.
            scope.Complete();
        }

        client.Close();

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

Konfigurace klienta určuje krátkou dobu, po kterou se zpráva dostane ke službě. Pokud zprávu nelze přenést během zadané doby trvání, vyprší platnost zprávy a přesune se do fronty nedoručených zpráv.

Poznámka:

Klient může zprávu doručit do fronty služby v zadaném čase. Abyste měli jistotu, že se služba nedoručených dopisů zobrazuje v akci, měli byste před spuštěním služby spustit klienta. Zpráva vyprší a doručí se do služby nedoručených zpráv.

Aplikace musí definovat, která fronta se má použít jako fronta nedoručených zpráv. Pokud není zadána žádná fronta, použije se výchozí transakční fronta nedoručených zpráv v rámci celého systému. V tomto příkladu klientská aplikace určuje vlastní frontu nedoručených zpráv aplikace.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <!-- use appSetting to configure MSMQ Dead Letter queue name -->
    <add key="deadLetterQueueName" value=".\private$\ServiceModelSamplesOrdersAppDLQ"/>
  </appSettings>

  <system.serviceModel>
    <client>
      <!-- Define NetMsmqEndpoint -->
      <endpoint name="OrderProcessorEndpoint"
                address="net.msmq://localhost/private/ServiceModelSamplesDeadLetter"
                binding="netMsmqBinding"
                bindingConfiguration="PerAppDLQBinding"
                contract="IOrderProcessor" />
    </client>

    <bindings>
      <netMsmqBinding>
        <binding name="PerAppDLQBinding"
                 deadLetterQueue="Custom"
                 customDeadLetterQueue="net.msmq://localhost/private/ServiceModelSamplesOrdersAppDLQ"
                 timeToLive="00:00:02"/>
      </netMsmqBinding>
    </bindings>
  </system.serviceModel>

</configuration>

Služba nedoručených zpráv čte zprávy z fronty nedoručených zpráv. Služba nedoručených zpráv implementuje IOrderProcessor kontrakt. Jeho implementace však nezpracovává objednávky. Služba nedoručených zpráv je klientská služba a nemá možnost zpracovávat objednávky.

Poznámka:

Fronta nedoručených zpráv je fronta klienta a je místní pro správce front klienta.

Implementace služby nedoručených zpráv kontroluje důvod selhání doručení zprávy a přijímá nápravná opatření. Důvod selhání zprávy je zaznamenán ve dvou výčtech DeliveryFailure a DeliveryStatus. Můžete načíst MsmqMessageProperty z obrázku OperationContext , jak je znázorněno v následujícím vzorovém kódu:

public void SubmitPurchaseOrder(PurchaseOrder po)
{
    Console.WriteLine("Submitting purchase order did not succeed ", po);
    MsmqMessageProperty mqProp =
                  OperationContext.Current.IncomingMessageProperties[
                  MsmqMessageProperty.Name] as MsmqMessageProperty;
    Console.WriteLine("Message Delivery Status: {0} ",
                                                mqProp.DeliveryStatus);
    Console.WriteLine("Message Delivery Failure: {0}",
                                               mqProp.DeliveryFailure);
    Console.WriteLine();
    …
}

Zprávy ve frontě nedoručených zpráv jsou zprávy, které jsou adresovány službě, která zprávu zpracovává. Proto když služba nedoručených zpráv čte zprávy z fronty, vrstva kanálu Windows Communication Foundation (WCF) najde neshodu v koncových bodech a neodesílají zprávu. V tomto případě je zpráva adresována službě zpracování objednávek, ale je přijata službou nedoručených zpráv. Chcete-li obdržet zprávu, která je adresována jinému koncovému bodu, filtr adresy, který odpovídá jakékoli adrese, je zadán v sadě ServiceBehavior. To je nutné k úspěšnému zpracování zpráv, které se čtou z fronty nedoručených zpráv.

V této ukázce služba nedoručených zpráv zprávu odešle znovu, pokud je důvodem selhání, že vypršel časový limit zprávy. Ze všech ostatních důvodů zobrazuje selhání doručení, jak je znázorněno v následujícím ukázkovém kódu:

// Service class that implements the service contract.
// Added code to write output to the console window.
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single, ConcurrencyMode=ConcurrencyMode.Single, AddressFilterMode=AddressFilterMode.Any)]
public class PurchaseOrderDLQService : IOrderProcessor
{
    OrderProcessorClient orderProcessorService;
    public PurchaseOrderDLQService()
    {
        orderProcessorService = new OrderProcessorClient("OrderProcessorEndpoint");
    }

    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public void SubmitPurchaseOrder(PurchaseOrder po)
    {
        Console.WriteLine("Submitting purchase order did not succeed ", po);
        MsmqMessageProperty mqProp = OperationContext.Current.IncomingMessageProperties[MsmqMessageProperty.Name] as MsmqMessageProperty;

        Console.WriteLine("Message Delivery Status: {0} ", mqProp.DeliveryStatus);
        Console.WriteLine("Message Delivery Failure: {0}", mqProp.DeliveryFailure);
        Console.WriteLine();

        // resend the message if timed out
        if (mqProp.DeliveryFailure == DeliveryFailure.ReachQueueTimeout ||
            mqProp.DeliveryFailure == DeliveryFailure.ReceiveTimeout)
        {
            // re-send
            Console.WriteLine("Purchase order Time To Live expired");
            Console.WriteLine("Trying to resend the message");

            // reuse the same transaction used to read the message from dlq to enqueue the message to app. queue
            orderProcessorService.SubmitPurchaseOrder(po);
            Console.WriteLine("Purchase order resent");
        }
    }

    // Host the service within this EXE console application.
    public static void Main()
    {
        // Create a ServiceHost for the PurchaseOrderDLQService type.
        using (ServiceHost serviceHost = new ServiceHost(typeof(PurchaseOrderDLQService)))
        {
            // Open the ServiceHostBase to create listeners and start listening for messages.
            serviceHost.Open();

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

Následující ukázka ukazuje konfiguraci zprávy s nedoručenou zprávou:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service
          name="Microsoft.ServiceModel.Samples.PurchaseOrderDLQService">
        <!-- Define NetMsmqEndpoint in this case, DLQ end point to read messages-->
        <endpoint address="net.msmq://localhost/private/ServiceModelSamplesOrdersAppDLQ"
                  binding="netMsmqBinding"
                  bindingConfiguration="DefaultBinding"
                  contract="Microsoft.ServiceModel.Samples.IOrderProcessor" />
      </service>
    </services>

    <client>
      <!-- Define NetMsmqEndpoint -->
      <endpoint name="OrderProcessorEndpoint"
                 address="net.msmq://localhost/private/ServiceModelSamplesDeadLetter"
                 binding="netMsmqBinding"
                 bindingConfiguration="SystemDLQBinding"
                 contract="IOrderProcessor" />
    </client>

    <bindings>
      <netMsmqBinding>
        <binding name="DefaultBinding" />
        <binding name="SystemDLQBinding"
                 deadLetterQueue="System"/>
      </netMsmqBinding>
    </bindings>
  </system.serviceModel>
</configuration>

Při spuštění ukázky existují 3 spustitelné soubory, které se mají spustit, abyste viděli, jak fronta nedoručených zpráv funguje pro každou aplikaci; klient, služba a služba nedoručených zpráv, které čte z fronty nedoručených zpráv pro každou aplikaci a znovu odešle zprávu službě. Všechny jsou konzolové aplikace s výstupem v oknech konzoly.

Poznámka:

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. Službu byste měli spustit a vypnout, aby se fronta vytvořila.

Při spuštění klienta zobrazí klient zprávu:

Press <ENTER> to terminate client.

Klient se pokusil zprávu odeslat, ale s krátkým vypršením časového limitu, platnost zprávy vypršela a je nyní zařazena do fronty nedoručených zpráv pro každou aplikaci.

Pak spustíte službu nedoručených zpráv, která přečte zprávu a zobrazí kód chyby a znovu odešle zprávu zpět do služby.

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

Submitting purchase order did not succeed
Message Delivery Status: InDoubt
Message Delivery Failure: ReachQueueTimeout

Purchase order Time To Live expired
Trying to resend the message
Purchase order resent

Služba se spustí a pak přečte znovu zprávu a zpracuje ji.

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

Processing Purchase Order: 97897eff-f926-4057-a32b-af8fb11b9bf9
        Customer: somecustomer.com
        OrderDetails
                Order LineItem: 54 of Blue Widget @unit price: $29.99
                Order LineItem: 890 of Red Widget @unit price: $45.89
        Total cost of this order: $42461.56
        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 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 kartu Funkce.

    3. Klikněte pravým tlačítkem myši na Soukromé fronty zpráv a vyberte Nová soukromá fronta.

    4. Zaškrtněte políčko Transactional (Transakce).

    5. Zadejte ServiceModelSamplesTransacted jako název nové fronty.

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

  4. Pokud chcete ukázku spustit v konfiguraci jednoho nebo více počítačů, odpovídajícím způsobem změňte názvy front, nahraďte localhost úplným názvem počítače a postupujte podle pokynů v části Spuštění ukázek windows Communication Foundation.

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

    <bindings>
        <netMsmqBinding>
            <binding name="TransactedBinding">
                <security mode="None"/>
            </binding>
        </netMsmqBinding>
    </bindings>
    

    Ujistěte se, že je koncový bod přidružený k vazbě, nastavením atributu koncového bindingConfiguration bodu.

  2. Před spuštěním ukázky nezapomeňte změnit konfiguraci na serveru DeadLetterService a klientovi.

    Poznámka:

    Nastavení security mode , které None odpovídá nastavení MsmqAuthenticationModea MsmqProtectionLevelMessage zabezpečení None.

Komentáře

Ve výchozím nastavení s přenosem vazby netMsmqBinding je povoleno zabezpečení. Dvě vlastnosti MsmqAuthenticationMode a MsmqProtectionLevelspolečně určují typ zabezpečení přenosu. Ve výchozím nastavení je režim ověřování nastaven Windows na a úroveň ochrany je nastavena na Sign. Aby služba MSMQ poskytovala funkci ověřování a podepisování, musí být součástí domény. Pokud tuto ukázku spustíte v počítači, který není součástí domény, zobrazí se následující chyba: "Certifikát řízení front zpráv uživatele neexistuje".