Upload
dima-dzuba
View
151
Download
5
Embed Size (px)
DESCRIPTION
Работа с очередями сообщений MSMQ, Open MQ, Rabbit MQ.
Citation preview
МАИ, каф 806, Сети ЭВМ
MESSAGE ORIENTED
ARCHITECTURE
Очереди сообщений
1
МАИ, каф 806, Сети ЭВМ
За что любить очереди?
Автоматический повтор попыток
соединения.
Отправитель или получатель могут
быть отключены от сети. Как только
они выйдут в “online”, сообщение будет
доставлено. Это может происходить
асинхронно, то есть нет
необходимости в том, чтобы
отправитель и получатель
одновременно находились в сети.
Гарантированная доставка.
Получатель читает данные из очереди
с удобной для себя интенсивностью.
Возможность масштабировать
количество обработчиков сообщений.
2
МАИ, каф 806, Сети ЭВМ
Введение
В настоящий момент существует несколько основных разработок в области промежуточного
программного обеспечения для работы с очередями сообщений. Наиболее известными
разработками являются такие системы очередей сообщений, как MSMQ, Sun Java System
Message Queue, IBM MQSeries, Oracle Advanced Queing, VMWare RabbitMQ.
Промежуточная среда MSMQ – разработка Microsoft для асинхронной передачи сообщений
внутри локальной сети, впервые появившаяся в составе операционной системы Windows.
Служба MSMQ позволяет произвольному набору приложений добавлять сообщения в
некоторую очередь, и произвольному же набору – читать сообщения из очереди.
Приложению, использующему MSMQ, доступны следующие основные операции:
добавить сообщение в очередь;
извлечь первое сообщение из очереди;
установить обработчик, вызываемый при появлении сообщения.
Структура сообщения определяется приложением, и может быть произвольной, с
ограничением на размер одного сообщения (4Мб для MSMQ 3.0)
3
МАИ, каф 806, Сети ЭВМ4
MSMQ. Обзор
MSMQ (Microsoft Message Queuing) – протокол гарантированной передачи данных между компьютерам.
Очередь (queue) – временное хранилище сообщений пересылаемых между компьютерами.
Основные возможности MSMQ:
COM-based access. Для доступа к сервисам MSMQ может быть использован простой COM интерфейс.
Интеграция с службами транзакций.
«Журналирование» сообщений в очереди.
Уведомление о получении сообщений отправляющей стороны.
Встроенные средства шифрования данных передаваемых по сети.
Поддержка сообщений с приоритетами.
Независимость от сетевого протокола
МАИ, каф 806, Сети ЭВМ5
MSMQ. Принцип работы
При отправке сообщения с использованием
MSMQ посылающему приложению
необходимо указать имя компьютера и
очереди, в которую его необходимо
доставить. После вызова приложением
функции отправки сообщение сохраняется в
локальной исходящей очереди. Затем MSMQ
определяет имя компьютера и очереди, куда
необходимо передать сообщение.
Возможны следующие случаи:
сообщение доставляется сразу в
указанную отправителем очередь
(прямая доставка);
сообщение посылается в некоторую
промежуточную очередь, определяемую
маршрутизатором службы сообщений;
MSMQ определяет, что сообщение
требуется разослать в несколько
очередей (возможность поддерживается
начиная с MSMQ 3.0).
МАИ, каф 806, Сети ЭВМ
Инфраструктура, необходимая для использования MSMQ
Служба MSMQ может работать как в составе домена Active Directory, так и при отсутствии
такого домена, но во втором случае невозможно использовать ряд возможностей MSMQ, а
именно:
не поддерживается шифрование передаваемых сообщений;
не поддерживаются общие очереди и механизмы их обнаружения;
не поддерживается маршрутизация сообщений и групповая рассылка сообщений.
В MSMQ существуют два вида очередей – общие (public) и частные (private). Как частные, так
и общие очереди могут либо использовать, либо не использовать транзакции, что задается
при создании очереди и не может быть изменено в дальнейшем.
Информация об общих очередях публикуется в службе каталогов Active Directory. Путь к
общей очереди имеет вид ComputerName\QueueName, возможна также запись пути в виде
.\QueueName для очереди на локальном компьютере.
6
МАИ, каф 806, Сети ЭВМ
Именование очередей
MSMQ поддерживает два вида имени очереди – прямой вид (direct name) и путь к очереди
(path name). При использовании частных очередей на удаленном компьютере обычно
необходимо использовать прямой путь к очереди. При использовании MSMQ программами на
.NET Framework прямой путь записывается следующим образом:
Formatname:DIRECT=OS:server01\QueueName – прямое имя общей очереди на
компьютере server01;
Formatname:DIRECT=OS:ws02\Private$\QueueName – прямое имя частной очереди на
компьютере ws02;
Formatname:DIRECT=TCP:192.168.30.1\private$\QueueName – прямое имя частной
очереди на компьютере с адресом 192.168.30.1.
Полноценная работа с очередями возможна только в пределах локальной или виртуально
частной сети, поскольку при чтении сообщений используется Windows RPC (в частности,
обращения на 135-й порт).
7
Вид Использование
FormatFORMATNAME:DIRECT={Имя Протокола}:{Путь}[PRIVATE$\]{Имя очереди}FORMATNAME:MULTICAST={IP адрес}:{Номер Порта}FORMATNAME:DL={GUID Распределенного Списка}[@{Имя Домена}]
Label LABEL:{Метка Очереди}
МАИ, каф 806, Сети ЭВМ
.NET Framework
Для работы с очередями сообщений используются классы из пространства
имен System.Messaging. Класс System.Messaging.MessageQueue содержит три группы
методов.
Статические методы для администрирования
очередей: Create, Delete, Exists, Purge.
Методы поиска общих очередей: GetPublicQueues, GetPublicQueuesByLabel и
другие. При их использовании можно создать приложение, которое переключается между
несколькими менеджерами очередей в пределах Active Directory, если один из них
выходит из строя.
Методы для работы с сообщениями (Send, Receive, Peek и другие), в том числе
позволяющие использоватьобработчик на завершение операции
(BeginPeek, BeginReceive).
При применении классов из System.Messaging возможно три варианта работы с очередями
сообщений:
работа с очередями, не использующими транзакции;
работа с очередями, поддерживающими транзакции, при использовании внутренних
транзакций MSMQ;
работа с очередями, поддерживающими транзакции, при использовании
распределенных транзакций COM+.
8
МАИ, каф 806, Сети ЭВМ
Сериализация и десериализация
Для сериализации и десериализации сообщений MSMQ могут использоваться
классы XMLMessageFormatter или BinaryMessageFormatter из пространства
имен System.Messaging.
Класс XMLMessageFormatter использует классSystem.Xml.Serialization.XmlSerializer, поэтому
при использовании XMLMessageFormatter должны учитываться все особенности
использования класса XmlSerializer.
Класс BinaryMessageFormatter аналогичным способом использует для сериализации
класс BinaryFormatter.
Рекомендованным для использования с MSMQ следует считать XMLMessageFormatter. Его
применение позволяет создать XSD схему для передаваемого сообщения. При
использовании MSMQ ни значительно меньший объем сообщения, создаваемого
классом BinaryMessageFormatter, ни его меньшее время работы не является
принципиальными факторами.
9
МАИ, каф 806, Сети ЭВМ10
MSMQ.Отправляем сообщение
МАИ, каф 806, Сети ЭВМ11
MSMQ. Отправляем сообщение
1. using System;
2. using System.Collections.Generic;
3. using System.ComponentModel;
4. using System.Data;
5. using System.Drawing;
6. using System.Text;
7. using System.Windows.Forms;
8. using System.Messaging;
9. namespace _15_MSMQSender
10. {
11. public partial class Form1 : Form
12. {
13. public Form1()
14. {
15. InitializeComponent();
16. }
17. private void mSend_Click(object sender, EventArgs e)
18. {
19. m_Queue.Send(mText.Text);
20. }
21. private void m_SendTransaction_Click(object sender, EventArgs e)
22. {
23. MessageQueueTransaction transaction;
24. transaction = new MessageQueueTransaction();
25. transaction.Begin();
26. m_QueueTransaction.Send(mText.Text, transaction);
27. transaction.Commit();
28. }
29. }
30. }
МАИ, каф 806, Сети ЭВМ12
MSMQ. Получаем сообщение
МАИ, каф 806, Сети ЭВМ13
MSMQ. Получаем сообщение
1. using System;
2. using System.Collections.Generic;
3. using System.ComponentModel;
4. using System.Data;
5. using System.Drawing;
6. using System.Text;
7. using System.Windows.Forms;
8. namespace _16_MSMQReader
9. {
10. public partial class Form1 : Form
11. {
12. public Form1()
13. {
14. InitializeComponent();
15. }
16. private void m_Read_Click(object sender, EventArgs e)
17. {
18. System.Messaging.Message msg = m_Queue.Receive();
19. String text = (String)msg.Body;
20. m_Text.Text += text + "\n";
21.
22. }
23. private void m_ReadTransaction_Click(object sender, EventArgs e)
24. {
25. System.Messaging.MessageQueueTransaction transaction;
26. transaction = new System.Messaging.MessageQueueTransaction();
27. transaction.Begin();
28. System.Messaging.Message msg = m_QueueTransaction.Receive(transaction);
29. String text = (String)msg.Body;
30. m_Text.Text += text + "\n";
31. transaction.Commit();
32. }
33. }
34. }
МАИ, каф 806, Сети ЭВМ14
MSMQ. Настраиваем очереди сообщений
Работает в Windows 2000, Windows XP (excluding Home Edition),
Windows Server 2003, Windows Vista (all editions), Win7, Win8 Pro.
Должна быть установлена и запущена служба Message Queuing
(входит в состав Windows но «по умолчанию» не ставится).
Должны быть созданы очереди MSMQ.
МАИ, каф 806, Сети ЭВМ15
MSMQ. Настраиваем очереди сообщений
Тип очереди
Частная
Публичная
Поддержка транзакций:
Поддерживаются
Не поддерживаются
Журнал
Включен
Выключен
МАИ, каф 806, Сети ЭВМ16
MSMQ
проверка существования и создание очереди
1. using System;
2. using System.Messaging;
3.
4. namespace FirstQueue
5. {
6. class Program
7. {
8. static void Main(string[] args)
9. {
10. try
11. {
12. if (!MessageQueue.Exists(@".\Private$\FirstQueue"))
13. {
14. MessageQueue.Create(@".\Private$\FirstQueue");
15. }
16. MessageQueue queue = new MessageQueue(@".\Private$\FirstQueue");
17. queue.Send("First Message ", " Label ");
18. }
19.
20. catch (MessageQueueException ex)
21. {
22. Console.WriteLine(ex.Message);
23. }
24. }
25. }
26. }
МАИ, каф 806, Сети ЭВМ
Виды очередей
Название Описание Адрес
PublicОчередь с входящими сообщениями, доступная через службу каталогов, например, ActiveDirectory.
MachineName\QueueName
PrivateОчередь с входящими сообщениями, доступная в WorkGroup.
MachineName\Private$\QueueName
Journal Журнал сообщений очередиMachineName\QueueName\Journal$
Journal Все отосланные и принятые сообщения. MachineName\Journal$
Dead-LetterОчередь сообщений, которые не удается доставить.
MachineName\DeadLetter$
Transactional Dead-Letter
Очередь неотосланных сообщений, которые участвовали в транзакции.
MachineName\XactDeadLetter$
17
МАИ, каф 806, Сети ЭВМ18
MSMQ
Поиск очередей
Статический метод MessageQueue
GetPublicQueuesByLable()
GetPublicQueuesByCategory()
GetPublicQueuesByMachine()
GetPublicQueue()
Пример
1. using System;
2. using System.Messaging;
3.
4. namespace FirstQueue
5. {
6. class Program
7. {
8. static void Main(string[] args)
9. {
10. foreach (MessageQueue queue in MessageQueue.GetPublicQueues())
11. {
12. Console.WriteLine(queue.Path);
13. }
14. }
15. }
16.}
МАИ, каф 806, Сети ЭВМ
Безопасность
только публичные очереди
Если вам необходима аутентификация сообщений, выставите значение свойства
MessageQueue.Authenticate в true. В клиентской части следует использовать свойство
Message.UseAuthentication. MSMQ для таких сообщений автоматически создает цифровую
подпись. Чтобы определить, каким криптопровайдером будет создаваться цифровая подпись,
используется свойство Message.AuthenticationProviderType (по умолчанию установленный в
CryptographicProviderType.RsaFull) или Message.AuthenticationProviderName.
using (MessageQueue queue = GetQueue()) {
queue.SetPermissions("Guest", MessageQueueAccessRights.FullControl,
AccessControlEntryType.Deny);
using (MessageQueueTransaction transaction = new MessageQueueTransaction())
{
transaction.Begin();
using (Message message = new Message("Hello")) {
message.UseAuthentication = true;
message.UseEncryption = true;
queue.Send(message, transaction);
}
transaction.Commit();}}
19
МАИ, каф 806, Сети ЭВМ21
Java Message System Queue
Полноценная поддержка Message-Oriented
архитектуры
Гарантированная доставка сообщений
Унифицированный формат сообщений
Возможность использования двух типов соединений:
Точка-точка (queue) – сообщение доставляется
одному получателю
Подписка-публикация (Topic) – сообщение
доставляется набору получателей
МАИ, каф 806, Сети ЭВМ
JMS.Connection
Имя Описание
createSession Create session
setClientID Set client identifier
getClientID Get client identifier
setExceptionListener Set exception listener (ExceptionListener)
getExceptionListener Get exception listener
getMetaData Get metadata for connection
createConnectionConsumer Create connection consumer
createDurableConnectionCo
nsumer
Create durable connection consumer
start Start incoming message delivery
stop Stop incoming message delivery
close Close connection
22
Основное назначение Connection – создавать
сессии по обмену сообщениями.
myConnection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
Транзактность
Режим уведомления брокера при
получении сообщения от брокера
Автоматически, при получении
Явно (например после обработки
сообщения ещё нужно его
обработать)
При прочтении определенного
числа сообщений из очереди, или
раз в несколько секунд
МАИ, каф 806, Сети ЭВМ
JMS. Работа с транзакциями
Позволяет работать с последовательностью сообщений как с одним.
1. Session mySession = myConnection.createSession(true, Session.SESSION_TRANSACTED);
2. if ( mySession.getTransacted() )
3. { /* Code here to handle transacted session */
4. }
5. else
6. { /* Code here to handle non-transacted session */
7. }
mySession.commit(); - все отправляемые сообщения отправляются, а получаемые
маркеруются как считанные.
mySession.rollback(); - все изменения откатываются
23
МАИ, каф 806, Сети ЭВМ
JMS. Сообщения
Сообщение состоит из
Заголовка, содержащего идентификационную информацию и информацию о роутинге
Дополнительных свойств (например для дополнительной идентификации)
Тела сообщения
24
Имя свойства Описание
JMSMessageID Message identifier (автоматически
генерируется брокером)
JMSDestination Destination to which message is sent
JMSReplyTo Destination to which to reply
JMSCorrelationID Link to related message
JMSDeliveryMode Delivery mode (persistent or nonpersistent)
JMSPriority Priority level
JMSTimestamp Time of transmission
JMSExpiration Expiration time
JMSType Message type
JMSRedelivered Has message been delivered before?
Тип сообщения Описание
TextMessage Содержит String
StreamMessage Позволяет записывать поток
примитивных типов
MapMessage Содержит именованные пары
имя-значение
ObjectMessage Содержит сериализованный
объект
BytesMessage Содержит поток байтов
Message Содержит пустое сообщение
(только заголовок и свойства)
МАИ, каф 806, Сети ЭВМ
Принцип написания программы
25
МАИ, каф 806, Сети ЭВМ26
JMS. Простой пример отправки сообщения
1. import javax.jms.*;
2. import javax.naming.*;
3. import java.io.*;
4. public class Chat {
5. public static void main(String [] args) throws Exception
6. {
7. ConnectionFactory myConnFactory;
8. Queue myQueue;
9. myConnFactory = new com.sun.messaging.ConnectionFactory();
10. Connection myConn = myConnFactory.createConnection();
11. Session mySess = myConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
12. myQueue = new com.sun.messaging.Queue("MyQueue");
13. MessageProducer myMsgProducer = mySess.createProducer(myQueue);
14. TextMessage myTextMsg = mySess.createTextMessage();
15. myTextMsg.setText("Hello World");
16. System.out.println("Sending Message: " + myTextMsg.getText());
17. myMsgProducer.send(myTextMsg);
18. mySess.close();
19. myConn.close();
20. }
21. }
МАИ, каф 806, Сети ЭВМ27
JMS. Простой пример получения сообщения
1. import javax.jms.*;
2. import javax.naming.*;
3. import java.io.*;
4. public class Chat {
5. public static void main(String [] args) throws Exception
6. {
7. ConnectionFactory myConnFactory;
8. Queue myQueue;
9. myConnFactory = new com.sun.messaging.ConnectionFactory();
10. Connection myConn = myConnFactory.createConnection();
11. Session mySess = myConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
12. myQueue = new com.sun.messaging.Queue("MyQueue");
13. MessageConsumer myMsgConsumer = mySess.createConsumer(myQueue);
14. myConn.start();
15. Message msg = myMsgConsumer.receive();
16. if (msg instanceof TextMessage) {
17. TextMessage txtMsg = (TextMessage) msg;
18. System.out.println("Read Message: " + txtMsg.getText());
19. }
20. mySess.close();
21. myConn.close();
22. }
23. }
МАИ, каф 806, Сети ЭВМ
MessageListener
import javax.jms.*;
public class Ex12_OpenMQReaderListner implements javax.jms.MessageListener {
public static void main(String [] args) throws Exception {
com.sun.messaging.ConnectionFactory myConnFactory= new com.sun.messaging.ConnectionFactory();
Connection myConn = myConnFactory.createConnection();
Session mySess = myConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue myQueue = new com.sun.messaging.Queue("MyQueue");
MessageConsumer myMsgConsumer = mySess.createConsumer(myQueue);
myMsgConsumer.setMessageListener(new Ex12_OpenMQReaderListner());
myConn.start();
System.in.read();
mySess.close();
myConn.close();
}
public void onMessage(Message msg) {
try {
if (msg instanceof TextMessage) {
TextMessage txtMsg = (TextMessage) msg;
System.out.println("Read Message: " + txtMsg.getText());
} }catch(JMSException ex){
ex.printStackTrace();
}}}28
МАИ, каф 806, Сети ЭВМ29
JMS.Установка и конфигурирование
Используем Open Message Queue (https://mq.dev.java.net/)
К проекту подключаем библиотеки:
imq.jar
jms.jar
Запускаем сервис для брокеров
c:\Program Files\Sun\MessageQueue\mq\bin\imqbrokerd.exe
Создаем и конфигурируем очереди сообщений
Запускаем c:\Program Files\Sun\MessageQueue\mq\bin\imqadmin.exe
Создаем брокер
Создаем очередь
Запускаем брокер
МАИ, каф 806, Сети ЭВМ30
JMS.Создание брокера
МАИ, каф 806, Сети ЭВМ31
JMS.Настройка очереди
Задаем имя очереди (MyQueue)
Выбираем тип
Queue
Destination
Указываем ограничения на
очередь и сообщения.
МАИ, каф 806, Сети ЭВМ
Что такое RabbitMQ
Сервер очередей
http://www.rabbitmq.com/download.html
Клиентские библиотеки для работы с сервером
http://www.rabbitmq.com/clients.html
http://www.rabbitmq.com/devtools.html
Встроенные механизмы для распределённости и кластеризации
МАИ, каф 806, Сети ЭВМ
Для чего
«Транспорт»
Отказоустойчивость
Производительность
МАИ, каф 806, Сети ЭВМ
Отличительные особенности RabbitMQ
Используется виртуальная машина Erlang
Относительная простота настройки и использования
Поддержка большинства ОС
Open source
Использование протокола AMQP
Классное название
МАИ, каф 806, Сети ЭВМ
Установка простого
RabbitMQ-сервера (Windows)
Установить Erlang
http://www.erlang.org/download.html
Установка RabbitMQ-сервера
http://www.rabbitmq.com/install-windows.html
Далее в консоли
сd \Program Files \RabbitMQ Server\rabbitmq_server-2.8.2\sbin
rabbitmq-service.bat start
rabbitmqctl start_app
PROFIT!
МАИ, каф 806, Сети ЭВМ
Federation/Shovel
Основная задача – «транспорт» между серверами очередей
Нет особых требований к соединению между серверами
Гарантированная доставка
http://www.rabbitmq.com/distributed.html
Настройка Shovel
http://www.rabbitmq.com/shovel.html
http://www.codeproject.com/Articles/309786/Rabbit-Mq-Shovel-Example
МАИ, каф 806, Сети ЭВМ
Кластеризация
Все узлы представляют собой «единое целое»
Стратегии кластеризации:
Mirror
High availability with Pacemaker
Необходимость хорошего LAN соединения между узлами кластера
http://www.rabbitmq.com/clustering.html
МАИ, каф 806, Сети ЭВМ
Аналоги
MSMQ
FioranoMQ
WebSphere
МАИ, каф 806, Сети ЭВМ
Пример работы с клиентской библиотекой для .NET
Где её найти
http://www.rabbitmq.com/download.html
МАИ, каф 806, Сети ЭВМ
Отправляем сообщения
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RabbitMQ.Client;
namespace RabbitMQSender
{
class Program
{
static void Main(string[] args)
{
string serverAddress = @"amqp://guest:guest@server:5672/";
string routingKey = "test_queue";
string message = "";
ConnectionFactory cf = new ConnectionFactory(); cf.Uri = serverAddress;
try
{
using (IConnection conn = cf.CreateConnection())//Создание соединения
{
using (IModel ch = conn.CreateModel()) //Открытие сессии, канала и модели
{
ch.QueueDeclare(routingKey, false, false, false, null); //Создание очереди
while (message != "Q")
{
message = Console.ReadLine();
ch.BasicPublish("", routingKey, null, Encoding.UTF8.GetBytes(message)); // Отправка сообщения
}
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
МАИ, каф 806, Сети ЭВМ
Принимаем сообщения
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RabbitMQ.Client;
namespace RabbitMQReciever
{
class Program
{
static void Main(string[] args)
{
string serverAddress = @"amqp://guest:guest@SCAVR:5672/";
string routingKey = "test_queue";
string message = "";
ConnectionFactory cf = new ConnectionFactory();
cf.Uri = serverAddress;
try
{
using (IConnection conn = cf.CreateConnection())
{
using (IModel ch = conn.CreateModel())
{
while (true)
{
BasicGetResult result = ch.BasicGet(routingKey, false); //Прием сообщения
if (result == null)
break;
else
{
ch.BasicAck(result.DeliveryTag, false); //Отправить подтверждение, что сообщение успешно принято
message = Encoding.UTF8.GetString(result.Body);
Console.WriteLine("Message: " + message);
}
}
}
}
Console.ReadKey(true);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}