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

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

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

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

class MsmqServer<RequestType, AnswerType>: 
        MsmqUser<RequestType, AnswerType>, IDisposable
    {
        // очередь приема запросов
        private MessageQueue queueReceive;
        // событие, вызываемое при приеме запроса       
        public event ProcessRequestEventHandler<RequestType, AnswerType>
            ProcessMessage;

Конструктор класса проверяет наличие очереди.

public MsmqServer(String queueReceiveName, QueueFormatter formatterType): 
            base(formatterType)
        {                       
            // создание очереди приема сообщений, если она не существует
            queueReceive = MsmqTools.CreateQueue(queueReceiveName,
                QueueType.Transactional);         
            queueReceive.Formatter = requestFormatter;
        }

В методе Dispose происходит закрытие используемых очередей.

public void Dispose()
        {
            queueReceive.Close();
            queueReceive.Dispose();
        }

Функции BeginReceive и EndReceive начинают и прекращают прием ответов сервера, изменяя обработчик события PeekComplete очереди ответов.

// начать прием запросов от клиента
        public void BeginReceive()
        {
            queueReceive.PeekCompleted += OnPeek;
            queueReceive.BeginPeek();           
        }   

        // прекратить прием запросов от клиента
        public void EndReceive()
        {            
            queueReceive.PeekCompleted -= OnPeek;
        }

Метод OnPeek – обработчик события PeekCompleted очереди с запросами. В одну транзакцию входит две операции с очередями – чтения запроса и отправка ответа на него. Для обработки принятого сообщения и создания ответа на него вызывается событие ProcessMessage. В поле ResponseQueue полученного сообщения содержится ссылка на очередь, в которую следует отправить ответ на обработанный запрос.

// обработчки события PeekCompleted очереди с запосами
        public void OnPeek(Object source, PeekCompletedEventArgs asyncResult)
        {
            // создание внутренней транзакции MSMQ 
            MessageQueueTransaction transaction = new MessageQueueTransaction();            
            // начало транзакции       
            transaction.Begin();
            try
            {               
                queueReceive.EndPeek(asyncResult.AsyncResult);
                // прием cообщения в рамках транзакции 
                Message message = queueReceive.Receive(transaction);
                
                // в поле ResponseQueue содержится ссылка на очередь, 
                // куда следует послать ответ на запрос
                MessageQueue queueResponse = message.ResponseQueue;
                try
                {
                    if (message.Body is RequestType)
                    {
                        RequestType request = (RequestType) message.Body;
                        // вызвать событие обработки запроса 
                        AnswerType answer = ProcessMessage(this, request, 
                            queueResponse);
                        if ((queueResponse != null) && (answer != null))
                        {               
                            Message answerMessage = new Message(answer, 
                                answerFormatter); 
                            answerMessage.Label = "Answer";
                            answerMessage.CorrelationId = message.Id;
                            answerMessage.Recoverable = Recoverable;

                            // послать собщение в рамках транзакции
                            queueResponse.Send(answerMessage, transaction);                   
                        }   
                    }
                }                    
                finally
                {
                    if (queueResponse != null)
                    {
                        queueResponse.Close();
                        queueResponse.Dispose();
                    }
                };                    

                // продолжить прием запросов
                BeginReceive();
                // завершить транзакцию 
                transaction.Commit();
            }
            catch (Exception e)
            {
                // отменить транзакцию в случае ошибки
                Console.WriteLine(e);
                transaction.Abort();  
                throw e;        
            }
        }   
    }
Листинг 5.3.

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

static class MsmqTools
    {             
        static public MessageQueue CreateQueue(String queueName)
        {
            return CreateQueue(queueName, QueueType.Transactional);
        }

        // функция проверяет наличие очереди и создает ее при необходимости
        static public MessageQueue CreateQueue(String queueName, 
            QueueType type)
        {
            MessageQueue messageQueue;            
            // если это частная очередь удаленного компьютера,
            // то при попытке проверки ее наличие возникает исключение
            try 
            {
                if (!MessageQueue.Exists(queueName))
                {
                    MessageQueue.Create(queueName, 
                        type == QueueType.Transactional);
                }
            }    
            catch(Exception)
            {
            }                       
            MessageQueue messageQueue = new MessageQueue(queueName);            
            return messageQueue;
        }
    }   
}

Следует отметить, что при работе с общими очередями можно обращаться к очереди по ее пути, например следующим образом.

queueName = @"Server\PublicQueue";

При использовании частных очередей на удаленном компьютере в большинстве случаев требуется применять прямое имя очереди.

queueName = @"Formatname:DIRECT=OS:Computer\Private$\PrivateName";

Имена используемых очередей следует хранить в конфигурационном файле программы.

5.5. Выводы по использованию MSMQ

Промежуточная среда Microsoft Message Queuing обеспечивает асинхронный обмен сообщениями и может быть использована программными компонентами распределенной системы в одном из следующих случаях:

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

Альтернативным способом использования MSMQ являются отложенные компоненты ( queued components ) среды COM+, которые будут рассмотрены в разделе, посвященном COM+. При использовании отложенных компонент MSMQ теряет одно из своих достоинств – клиент должен иметь доступ к интерфейсу удаленной компоненты, как и в случае использования любых других COM+ компонент. Кроме того, существует возможность использовать MSMQ как канал в .NET Remoting, для чего необходимо создать собственный канал, что будет проделано в соответствующей теме. Таким образом, MSMQ является не только самостоятельной промежуточной средой, но и может быть использовано другими промежуточными средами как асинхронный канал передачи данных.

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