Обработка подозрительных сообщений в MSMQ 4.0Poison Message Handling in MSMQ 4.0

В этом образце демонстрируется обработка подозрительных сообщений в службе.This sample demonstrates how to perform poison message handling in a service. Этот пример основан на образце транзакционной привязки MSMQ .This sample is based on the Transacted MSMQ Binding sample. В этом образце используется привязка netMsmqBinding.This sample uses the netMsmqBinding. Служба представляет собой резидентное консольное приложение, позволяющее наблюдать за получением службой сообщений из очереди.The service is a self-hosted console application to enable you to observe the service receiving queued messages.

При использовании очередей клиент взаимодействует со службой посредством очереди.In queued communication, the client communicates to the service using a queue. Конкретно, клиент отправляет сообщения в очередь.More precisely, the client sends messages to a queue. Служба получает сообщения из очереди.The service receives messages from the queue. Поэтому клиенту и службе не обязательно выполняться одновременно, чтобы взаимодействовать посредством очереди.The service and client therefore, do not have to be running at the same time to communicate using a queue.

Подозрительное сообщение - это сообщение, которое повторно считывается из очереди, если служба, читающая сообщение, не может его обработать и завершает транзакцию, в рамках которой считывается сообщение.A poison message is a message that is repeatedly read from a queue when the service reading the message cannot process the message and therefore terminates the transaction under which the message is read. В таких случаях предпринимается еще одна попытка считывания сообщения.In such cases, the message is retried again. Теоретически этот процесс может продолжаться бесконечно, если существует проблема с сообщением.This can theoretically go on forever if there is a problem with the message. Это может произойти только при использовании транзакций для чтения из очереди и вызове операции службы.This can only occur when you use transactions to read from the queue and invoke the service operation.

Возможность поддержки обнаружения подозрительных сообщений (от ограниченного до полного) привязкой NetMsmqBinding зависит от версии MSMQ.Based on the version of MSMQ, the NetMsmqBinding supports limited detection to full detection of poison messages. После того как сообщение было распознано как подозрительное, оно может обрабатываться несколькими способами.After the message has been detected as poisoned, then it can be handled in several ways. Поддержка обработки подозрительных сообщений (от ограниченной до полной) привязкой NetMsmqBinding зависит от версии MSMQ.Again, based on the version of MSMQ, the NetMsmqBinding supports limited handling to full handling of poison messages.

В этом примере показаны ограниченные опасные средства, предоставляемые на платформе Windows Server 2003 и Windows XP, а также полностью опасные средства, предоставляемые в Windows Vista.This sample illustrates the limited poison facilities provided on Windows Server 2003 and Windows XP platform and the full poison facilities provided on Windows Vista. В обоих примерах цель заключается в перемещении поврежденного сообщения из очереди в другую очередь.In both samples, the objective is to move the poison message out of the queue to another queue. Затем эта очередь может обслуживаться службой подозрительных сообщений.That queue can then be serviced by a poison message service.

Образец обработки подозрительных сообщений в MSMQ v4.0.MSMQ v4.0 Poison Handling Sample

В Windows Vista служба MSMQ предоставляет механизм подозрительных вложенных очередей, который можно использовать для хранения подозрительных сообщений.In Windows Vista, MSMQ provides a poison subqueue facility that can be used to store poison messages. В этом примере демонстрируется Лучшая практика работы с подозрительными сообщениями с помощью Windows Vista.This sample demonstrates the best practice of dealing with poison messages using Windows Vista.

Обнаружение подозрительных сообщений в Windows Vista является сложным.The poison message detection in Windows Vista is sophisticated. Обнаружению таких сообщений способствуют три свойства.There are 3 properties that help with detection. Свойство ReceiveRetryCount обозначает, сколько раз заданное сообщение перечитывается из очереди и передается приложению для обработки.The ReceiveRetryCount is number of times a given message is re-read from the queue and dispatched to the application for processing. Сообщение повторно считывается из очереди, если оно повторно помещено в очередь, потому что его не удается передать приложению, или приложение выполняет откат транзакции в операции службы.A message is re-read from the queue when it is put back into the queue because the message cannot be dispatched to the application or the application rolls back the transaction in the service operation. Свойство MaxRetryCycles указывает, сколько раз сообщение перемещается в очередь повторных попыток.MaxRetryCycles is the number of times the message is moved to the retry queue. При достижении ReceiveRetryCount сообщение перемещается в очередь повторных попыток.When ReceiveRetryCount is reached, the message is moved to the retry queue. Свойство RetryCycleDelay - это промежуток времени, по истечении которого сообщение перемещается из очереди повторных попыток в основную очередь.The property RetryCycleDelay is the time delay after which the message is moved from the retry queue back to the main queue. Счетчик ReceiveRetryCount обнуляется.The ReceiveRetryCount is reset to 0. Делается еще одна попытка прочесть сообщение.The message is tried again. Если все попытки прочтения сообщения оказываются неудачными, сообщение помечается как подозрительное.If all attempts to read the message have failed, then the message is marked as poisoned.

После этого сообщение обрабатывается в соответствии с параметрами, заданными в перечислении ReceiveErrorHandling.Once the message is marked as poisoned, the message is dealt with according to the settings in the ReceiveErrorHandling enumeration. Ниже еще раз перечислены возможные значения.To reiterate the possible values:

  • Fault (по умолчанию): происходит сбой прослушивателя и узла службы.Fault (default): To fault the listener and also the service host.

  • Drop: сообщение отбрасывается.Drop: To drop the message.

  • Переместить: для перемещения сообщения в подочередь подозрительных сообщений.Move: To move the message to the poison message subqueue. Это значение доступно только в Windows Vista.This value is available only on Windows Vista.

  • Reject: сообщение отклоняется и возвращается в очередь недоставленных сообщений отправителя.Reject: To reject the message, sending the message back to the sender's dead-letter queue. Это значение доступно только в Windows Vista.This value is available only on Windows Vista.

В этом образце демонстрируется использование команды Move для перемещения опасного сообщения о сбое.The sample demonstrates using the Move disposition for the poison message. Move приводит к перемещению сообщения в подочередь подозрительных сообщений.Move causes the message to move to the poison subqueue.

Контракт службы IOrderProcessor определяет одностороннюю службу, которую можно использовать с очередями.The service contract is IOrderProcessor, which defines a one-way service that is suitable for use with queues.

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

Операция службы отображает сообщение о том, что она обрабатывает заказ.The service operation displays a message stating it is processing the order. Чтобы продемонстрировать функцию подозрительных сообщений, SubmitPurchaseOrder операция службы создает исключение для отката транзакции при случайном вызове службы.To demonstrate the poison message functionality, the SubmitPurchaseOrder service operation throws an exception to roll back the transaction on a random invocation of the service. В результате сообщение помещается обратно в очередь.This causes the message to be put back in the queue. В конечном счете это сообщение помечается как подозрительное.Eventually the message is marked as poison. Конфигурация настроена на перемещение подозрительного сообщения в подочередь подозрительных сообщений.The configuration is set to move the poison message to the poison subqueue.

// Service class that implements the service contract.
// Added code to write output to the console window.
public class OrderProcessorService : IOrderProcessor
{
    static Random r = new Random(137);

    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public void SubmitPurchaseOrder(PurchaseOrder po)
    {

        int randomNumber = r.Next(10);

        if (randomNumber % 2 == 0)
        {
            Orders.Add(po);
            Console.WriteLine("Processing {0} ", po);
        }
        else
        {
            Console.WriteLine("Aborting transaction, cannot process purchase order: " + po.PONumber);
            Console.WriteLine();
            throw new Exception("Cannot process purchase order: " + po.PONumber);
        }
    }

    public static void OnServiceFaulted(object sender, EventArgs e)
    {
        Console.WriteLine("Service Faulted");
    }

    // 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 (!System.Messaging.MessageQueue.Exists(queueName))
            System.Messaging.MessageQueue.Create(queueName, true);

        // Get the base address that is used to listen for WS-MetaDataExchange requests.
        // This is useful to generate a proxy for the client.
        string baseAddress = ConfigurationManager.AppSettings["baseAddress"];

        // Create a ServiceHost for the OrderProcessorService type.
        ServiceHost serviceHost = new ServiceHost(typeof(OrderProcessorService), new Uri(baseAddress));

        // Hook on to the service host faulted events.
        serviceHost.Faulted += new EventHandler(OnServiceFaulted);

        // Open the ServiceHostBase 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();

        if(serviceHost.State != CommunicationState.Faulted) {
            serviceHost.Close();
        }

    }
}

Конфигурация службы включает следующие свойства подозрительных сообщений: receiveRetryCount, maxRetryCycles, retryCycleDelay и receiveErrorHandling, как показано в следующем файле конфигурации.The service configuration includes the following poison message properties: receiveRetryCount, maxRetryCycles, retryCycleDelay, and receiveErrorHandling as shown in the following configuration file.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <!-- Use appSetting to configure MSMQ queue name. -->
    <add key="queueName" value=".\private$\ServiceModelSamplesPoison" />
    <add key="baseAddress" value="http://localhost:8000/orderProcessor/poisonSample"/>
  </appSettings>
  <system.serviceModel>
    <services>
      <service
              name="Microsoft.ServiceModel.Samples.OrderProcessorService">
        <!-- Define NetMsmqEndpoint -->
        <endpoint address="net.msmq://localhost/private/ServiceModelSamplesPoison"
                  binding="netMsmqBinding"
                  bindingConfiguration="PoisonBinding"
                  contract="Microsoft.ServiceModel.Samples.IOrderProcessor" />
      </service>
    </services>

    <bindings>
      <netMsmqBinding>
        <binding name="PoisonBinding"
                 receiveRetryCount="0"
                 maxRetryCycles="1"
                 retryCycleDelay="00:00:05"
                 receiveErrorHandling="Move">
        </binding>
      </netMsmqBinding>
    </bindings>
  </system.serviceModel>
</configuration>

Обработка сообщений из очереди подозрительных сообщенийProcessing messages from the poison message queue

Служба подозрительных сообщений считывает сообщения из конечной очереди подозрительных сообщений и обрабатывает их.The poison message service reads messages from the final poison message queue and processes them.

Сообщения в очереди подозрительных сообщений - это сообщения, адресованные обрабатывающей сообщение службе, которая может отличаться от конечной точки службы подозрительных сообщений.Messages in the poison message queue are messages that are addressed to the service that is processing the message, which could be different from the poison message service endpoint. Таким образом, когда служба подозрительных сообщений считывает сообщения из очереди, уровень канала WCF находит несоответствие в конечных точках и не отправляет сообщение.Therefore, when the poison message service reads messages from the queue, the WCF channel layer finds the mismatch in endpoints and does not dispatch the message. В этом случае сообщение адресуется службе, обрабатывающей заказы, но получает его служба подозрительных сообщений.In this case, the message is addressed to the order processing service but is being received by the poison message service. Чтобы продолжать получать сообщение, даже если оно адресовано другой конечной точке, необходимо добавить поведение ServiceBehavior для фильтрации адресов, в котором критерием соответствия будет соответствие любой конечной точке службы, которой адресовано сообщение.To continue to receive the message even if the message is addressed to a different endpoint, we must add a ServiceBehavior to filter addresses where the match criterion is to match any service endpoint the message is addressed to. Это необходимо для успешной обработки сообщений, считываемых из очереди подозрительных сообщений.This is required to successfully process messages that you read from the poison message queue.

Реализация самой службы подозрительных сообщений очень похожа на реализацию службы.The poison message service implementation itself is very similar to the service implementation. Она реализует контракт и обрабатывает заказы.It implements the contract and processes the orders. Ниже приведен пример кода.The code example is as follows.

// Service class that implements the service contract.
// Added code to write output to the console window.
[ServiceBehavior(AddressFilterMode=AddressFilterMode.Any)]
public class OrderProcessorService : IOrderProcessor
{
    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public void SubmitPurchaseOrder(PurchaseOrder po)
    {
        Orders.Add(po);
        Console.WriteLine("Processing {0} ", po);
    }

    public static void OnServiceFaulted(object sender, EventArgs e)
    {
        Console.WriteLine("Service Faulted...exiting app");
        Environment.Exit(1);
    }

    // Host the service within this EXE console application.
    public static void Main()
    {

        // Create a ServiceHost for the OrderProcessorService type.
        ServiceHost serviceHost = new ServiceHost(typeof(OrderProcessorService));

        // Hook on to the service host faulted events.
        serviceHost.Faulted += new EventHandler(OnServiceFaulted);

        serviceHost.Open();

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

        // Close the ServiceHostBase to shutdown the service.
        if(serviceHost.State != CommunicationState.Faulted)
        {
            serviceHost.Close();
        }
    }

В отличие от службы обработки заказов, считывающей сообщения из очереди заказов, Служба подозрительных сообщений считывает сообщения из подочереди подозрительных сообщений.Unlike the order processing service that reads messages from the order queue, the poison message service reads messages from the poison subqueue. Очередь подозрительных сообщений — это подочередь основной очереди с именем "подозрительный" и автоматически создаваемая службой MSMQ.The poison queue is a subqueue of the main queue, is named "poison" and is automatically generated by MSMQ. Чтобы получить доступ к нему, укажите имя основной очереди, затем ";" и имя подочереди, в данном случае — "подозрительный", как показано в следующем образце конфигурации.To access it, provide the main queue name followed by a ";" and the subqueue name, in this case -"poison", as shown in the following sample configuration.

Примечание

В образце для MSMQ v3.0 очередь подозрительных сообщений является не вложенной очередью, а очередью, в которую было перемещено сообщение.In the sample for MSMQ v3.0, the poison queue name is not a sub-queue, rather the queue that we moved the message to.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="Microsoft.ServiceModel.Samples.OrderProcessorService">
        <!-- Define NetMsmqEndpoint -->
        <endpoint address="net.msmq://localhost/private/ServiceModelSamplesPoison;poison"
                  binding="netMsmqBinding"
                  contract="Microsoft.ServiceModel.Samples.IOrderProcessor" >
        </endpoint>
      </service>
    </services>

  </system.serviceModel>
</configuration>

При выполнении образца действия клиента, службы и службы подозрительных сообщений отображаются в окнах консоли.When you run the sample, the client, service, and poison message service activities are displayed in console windows. Можно видеть, как служба получает сообщения от клиента.You can see the service receive messages from the client. Нажмите клавишу ВВОД в каждом окне консоли, чтобы завершить работу служб.Press ENTER in each console window to shut down the services.

Служба начинает работать, обрабатывать заказы и в произвольном порядке завершать обработку.The service starts running, processing orders and at random starts to terminate processing. Если появляется сообщение о том, что заказ обработан, можно снова запустить клиент для отправки другого сообщения, пока не будет видно, что служба действительно завершила обработку сообщения.If the message indicates it has processed the order, you can run the client again to send another message until you see the service has actually terminated a message. В зависимости от заданных параметров подозрительных сообщений перед помещением сообщения в конечную очередь подозрительных сообщений предпринимается одна попытка его обработки.Based on the configured poison settings, the message is tried once for processing before moving it to the final poison queue.

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

Processing Purchase Order: 0f063b71-93e0-42a1-aa3b-bca6c7a89546
        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

Processing Purchase Order: 5ef9a4fa-5a30-4175-b455-2fb1396095fa
        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

Aborting transaction, cannot process purchase order: 23e0b991-fbf9-4438-a0e2-20adf93a4f89

Запустите службу подозрительных сообщений, чтобы считать подозрительное сообщение из очереди подозрительных сообщений.Start up the poison message service to read the poisoned message from the poison queue. В этом примере служба подозрительных сообщений считывает сообщение и обрабатывает его.In this example, the poison message service reads the message and processes it. Можно видеть, что заказ на покупку, обработка которого была завершена и который был помечен как подозрительный, считывается службой подозрительных сообщений.You could see that the purchase order that was terminated and poisoned is read by the poison message service.

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

Processing Purchase Order: 23e0b991-fbf9-4438-a0e2-20adf93a4f89
        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

Настройка, сборка и выполнение образцаTo set up, build, and run the sample

  1. Убедитесь, что вы выполнили однократную процедуру настройки для Windows Communication Foundation примеров.Ensure that you have performed the One-Time Setup Procedure for the Windows Communication Foundation Samples.

  2. При первом запуске служба проверит наличие очереди.If the service is run first, it will check to ensure that the queue is present. Если очередь отсутствует, служба ее создаст.If the queue is not present, the service will create one. Можно сначала запустить службу, чтобы создать очередь, либо создать ее с помощью диспетчера очередей MSMQ.You can run the service first to create the queue, or you can create one via the MSMQ Queue Manager. Чтобы создать очередь в Windows 2008, выполните следующие шаги.Follow these steps to create a queue in Windows 2008.

    1. Откройте диспетчер сервера в Visual Studio 2012.Open Server Manager in Visual Studio 2012.

    2. Разверните вкладку функции .Expand the Features tab.

    3. Щелкните правой кнопкой мыши частные очереди сообщений и выберите создать, Частная очередь.Right-click Private Message Queues, and select New, Private Queue.

    4. Установите флажок транзакционная .Check the Transactional box.

    5. Введите в ServiceModelSamplesTransacted качестве имени новой очереди.Enter ServiceModelSamplesTransacted as the name of the new queue.

  3. Чтобы создать выпуск решения на языке C# или Visual Basic .NET, следуйте инструкциям в разделе Building the Windows Communication Foundation Samples.To build the C# or Visual Basic .NET edition of the solution, follow the instructions in Building the Windows Communication Foundation Samples.

  4. Чтобы запустить пример в конфигурации с одним или несколькими компьютерами, измените имена очередей, чтобы они отражали фактическое имя узла вместо localhost, и следуйте инструкциям в разделе Запуск примеров Windows Communication Foundation.To run the sample in a single- or cross-computer configuration, change the queue names to reflect the actual hostname instead of localhost and follow the instructions in Running the Windows Communication Foundation Samples.

По умолчанию с транспортом привязки netMsmqBinding безопасность включена.By default with the netMsmqBinding binding transport, security is enabled. Тип безопасности транспорта определяется двумя свойствами: MsmqAuthenticationMode и MsmqProtectionLevel.Two properties, MsmqAuthenticationMode and MsmqProtectionLevel, together determine the type of transport security. По умолчанию задан режим проверки подлинности Windows и уровень защиты Sign.By default, the authentication mode is set to Windows and the protection level is set to Sign. Чтобы служба MSMQ обеспечивала возможности проверки подлинности и подписывания, она должна входить в домен.For MSMQ to provide the authentication and signing feature, it must be part of a domain. При выполнении этого примера на компьютере, не входящем в домен, возникает следующая ошибка: "User's internal message queuing certificate does not exist" (не существует внутреннего сертификата очереди сообщений пользователя).If you run this sample on a computer that is not part of a domain, you receive the following error: "User's internal message queuing certificate does not exist".

Выполнение образца на компьютере, входящем в рабочую группуTo run the sample on a computer joined to a workgroup

  1. Если компьютер не входит в домен, отключите безопасность транспорта, задав для режима проверки подлинности и уровня защиты значение None, как показано в следующем образце конфигурации.If your computer is not part of a domain, turn off transport security by setting the authentication mode and protection level to None as shown in the following sample configuration:

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

    Обеспечьте связь конечной точки с привязкой, задав атрибут bindingConfiguration конечной точки.Ensure the endpoint is associated with the binding by setting the endpoint's bindingConfiguration attribute.

  2. Перед запуском примера убедитесь, что вы изменили конфигурацию на Поисонмессажесервер, сервере и клиенте.Ensure that you change the configuration on the PoisonMessageServer, server, and the client before you run the sample.

    Примечание

    Задание для security mode значения None эквивалентно заданию для параметров безопасности MsmqAuthenticationMode, MsmqProtectionLevel и Message значения None.Setting security mode to None is equivalent to setting MsmqAuthenticationMode, MsmqProtectionLevel, and Message security to None.

  3. Чтобы обеспечить обмен метаданными, необходимо зарегистрировать URL-адрес с привязкой http.In order for Meta Data Exchange to work, we register a URL with http binding. Это требует выполнения службы в командном окне с повышенными привилегиями.This requires that the service run in an elevated command window. В противном случае возникнет исключение, например: Unhandled Exception: System.ServiceModel.AddressAccessDeniedException: HTTP could not register URL http://+:8000/ServiceModelSamples/service/. Your process does not have access rights to this namespace (see https://go.microsoft.com/fwlink/?LinkId=70353 for details). ---> System.Net.HttpListenerException: Access is denied .Otherwise, you get an exception such as: Unhandled Exception: System.ServiceModel.AddressAccessDeniedException: HTTP could not register URL http://+:8000/ServiceModelSamples/service/. Your process does not have access rights to this namespace (see https://go.microsoft.com/fwlink/?LinkId=70353 for details). ---> System.Net.HttpListenerException: Access is denied.

Важно!

Образцы уже могут быть установлены на компьютере.The samples may already be installed on your computer. Перед продолжением проверьте следующий каталог (по умолчанию).Check for the following (default) directory before continuing.

<InstallDrive>:\WF_WCF_Samples

Если этот каталог не существует, перейдите к примерам Windows Communication Foundation (WCF) и Windows Workflow Foundation (WF) для платформа .NET Framework 4 , чтобы скачать все Windows Communication Foundation (WCF) и WFWF примеры.If this directory does not exist, go to Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF) Samples for .NET Framework 4 to download all Windows Communication Foundation (WCF) and WFWF samples. Этот образец расположен в следующем каталоге.This sample is located in the following directory.

<InstallDrive>:\WF_WCF_Samples\WCF\Basic\Binding\Net\MSMQ\Poison\MSMQ4