Опубликован: 11.05.2007 | Доступ: свободный | Студентов: 1601 / 158 | Оценка: 4.36 / 4.25 | Длительность: 16:06:00
Лекция 6:

Microsoft Message Queuing (MSMQ) – промежуточная среда обмена сообщениями

< Лекция 5 || Лекция 6: 12345 || Лекция 7 >

5.4. Использование очередей сообщений MSMQ в .NET Framework

Для работы с очередями сообщений используются классы из пространства имен System.Messaging. Класс System.Messaging.MessageQueue содержит три группы методов.

  • Статические методы для администрирования очередей: Create, Delete, Exists, Purge.
  • Методы поиска общих очередей: GetPublicQueues, GetPublicQueuesByLabel и другие. При их использовании можно создать приложение, которое переключается между несколькими менеджерами очередей в пределах Active Directory, если один из них выходит из строя.
  • Методы для работы с сообщениями ( Send, Receive, Peek и другие), в том числе позволяющие использовать обработчик на завершение операции ( BeginPeek, BeginReceive ).

При применении классов из System.Messaging возможно три варианта работы с очередями сообщений:

  • работа с очередями, не использующими транзакции;
  • работа с очередями, поддерживающими транзакции, при использовании внутренних транзакций MSMQ;
  • работа с очередями, поддерживающими транзакции, при использовании распределенных транзакций COM+.

Определенной трудностью при использовании MSMQ в .NET Framework являются различия по использованию разных видов очередей. В частности, для очередей без транзакций можно установить обработчик на завершение приема сообщения, а для очередей с транзакциями этот способ неприемлем, поскольку само чтение сообщения должно быть оформлено как часть транзакции. Для обоих видов очередей можно поставить обработчик на появление сообщения в очереди, что и является рекомендованным способом.

Для сериализации и десериализации сообщений MSMQ могут использоваться классы XMLMessageFormatter или BinaryMessageFormatter из пространства имен System.Messaging. Класс XMLMessageFormatter использует класс System.Xml.Serialization.XmlSerializer, описанный ранее в теме о сериализации, поэтому при использовании XMLMessageFormatter должны учитываться все особенности использования класса XmlSerializer. Класс BinaryMessageFormatter аналогичным способом использует для сериализации класс BinaryFormatter.

Поскольку классы BinaryFormatter и XmlSerializer имеют различные ограничения на сериализуемые классы и используют совершенно различные процедуры сериализации, в нетривиальном случае переход BinaryMessageFormatter на XMLMessageFormatter или наоборот может привести к определенным изменениям в исходном коде программных компонент. Рекомендованным для использования с MSMQ следует считать XMLMessageFormatter. Его применение позволяет создать XSD схему для передаваемого сообщения. При использовании MSMQ ни значительно меньший объем сообщения, создаваемого классом BinaryMessageFormatter, ни его меньшее время работы не является принципиальными факторами.

Ниже рассмотрено вспомогательное пространство имен с классами общего вида, реализующими модель "запрос-ответ" при использовании внутренних транзакций MSMQ (рис. 5.2).

Обслуживание запросов клиентов при использовании MSMQ

Рис. 5.2. Обслуживание запросов клиентов при использовании MSMQ

Программа использует пространство имен с классами передачи сообщений System.Messaging и пространство имен с коллекциями общего вида.

using System;
using System.Messaging;
using System.Collections.Generic;

Классы используют два делегата общего вида, которые будут связаны с событиям обработки сообщения сервером и получения ответа клиентом.

namespace Seva.Msmq
{
    // типы очередей
    enum QueueType  {NonTransactional, Transactional};
    // типы классов форматирования
    enum QueueFormatter {Binary, Xml};
        
    // делегат общего вида для обработки сервером сообщений клиента
    delegate AnswerType ProcessRequestEventHandler
        <RequestType, AnswerType>(Object sender, RequestType request, 
        MessageQueue queueResponse);

    // делегат общего вида для обработки ответов сервера клиентом
    delegate void ProcessAnswerEventHandler<RequestType, AnswerType>
        (Object sender, RequestType request, AnswerType answer);

Абстрактный класс MSMQUser, наследуемый классами MSMQServer и MSMQClient.

public abstract class MsmqUser
    {
        // использование восстанавливаемых сообщений
        private bool recoverable = false;            
        public bool Recoverable   
 {
            get  {
                return recoverable;
            }
            set  {
                recoverable = value;
            } 
        }

        // объекты форматирования для посылки  приема сообщений
        protected IMessageFormatter requestFormatter;
        protected IMessageFormatter answerFormatter;
        //
        public MsmqUser(QueueFormatter formatterType)
        {
            if (formatterType == QueueFormatter.Xml)
            {
                requestFormatter =  new XmlMessageFormatter(
                    new Type[]{typeof(RequestType)}); 
                answerFormatter =  new XmlMessageFormatter(
                    new Type[]{typeof(AnswerType)});
            }        
            if (formatterType == QueueFormatter.Binary)
            {
                requestFormatter =  new BinaryMessageFormatter(); 
                answerFormatter =  new BinaryMessageFormatter();
            }
        }
    }
Листинг 5.1.

Класс общего вида, посылающий через MSMQ запросы и получающий ответы на них.

class MsmqClient<RequestType, AnswerType> : 
        MsmqUser<RequestType, AnswerType>, IDisposable
    {
        // очереди для отсылки запросов и приема ответов
        private MessageQueue queueSend;
        private MessageQueue queueReceive;
        // список необслуженных запросов
        private Dictionary<String, RequestType> messages;  
        public Dictionary<String, RequestType> Messages 
        {
            get { return messages;}
        }
        // событие, вызываемое при приеме ответа
        public event ProcessAnswerEventHandler<RequestType, AnswerType> 
            ProcessAnswer;
< Лекция 5 || Лекция 6: 12345 || Лекция 7 >