По работе возникла задача: распространять справочники через Biztalk, сами справочники достаточно большие – более 300 мегабайт. Было принято решение использовать MSMQ для получения сверх больших сообщений. А теперь подробнее, что для этого потребовалось сделать.
Конечно же первое что можно сделать это погуглив найти пример на MSDN как всё это реализовать (далее я его опишу на русском совместно с изменениями), но сразу оговорюсь что у этого примера есть небольшой – нельзя настроить размер части на которые делится сообщение, что может быть необходимо для различных задач. Итак приступим.
Для разработки нам понадобится:
- Visual Studio 2010 SP1
- Biztalk Server 2010 SDK
- Biztalk Server 2010 (для тестов)
- Желание во всём разобраться
Открываем проект <Путь к Biztalk Server 2010 SDK>AdaptersUsage MSMQLarge LargeMessages.sln. Видим что решение содержит два проекта: один из них на С++.NET, второй на C#. Для начала нам нужен первый, чтобы реализовать Возможность самому выбирать размер на которое дробится наше сообщение в очереди необходимо кое-что подправить в классе. Как видно из исходного кода размер передаётся в функции:
MQSendLargeMessage(unmanagedQueueData->queueHandle,
&(messageData->message),
MQ_SINGLE_MESSAGE,
MQRTLARGE_USE_DEFAULT_PART_SIZE);
По умолчанию MQRTLARGE_USE_DEFAULT_PART_SIZE определенно равным нулю, что означает использование размера по усмотрению сервера. Для своих целей мы добавим приватную переменную dwQueuePartSize и соответственно изменим приватную функцию Init(…)
void Init(String* formatName, bool useAuthentication, DWORD dwQueuePartSize)
{
this->formatName = formatName;
this->useAuthentication = useAuthentication;
this->dwQueuePartSize=dwQueuePartSize;
AllocUnmanagedQueueData();
}
Теперь она имеет дополнительный параметр отвечающий за установку размера при инициализации. Теперь нам необходимо соответствующим образом модифицировать конструкторы, которую использую эту функцию.
LargeMessageQueue(String* formatName, bool useAuthentication)
{
Init(formatName, useAuthentication, 0);
}
LargeMessageQueue(String* formatName)
{
Init(formatName, false, 0);
}
Сейчас можно добавить наш конструктор который принимает соответствующее значение:
LargeMessageQueue(String* formatName, DWORD dwQueuePartSize)
{
Init(formatName, false, dwQueuePartSize);
}
LargeMessageQueue(String* formatName, bool useAuthentication, DWORD dwQueuePartSize)
{
Init(formatName, useAuthentication, dwQueuePartSize);
}
Мы продублировали два стандартных конструктора, для того чтобы можно было устанавливать произвольный размер. Небольшое замечание: можно было бы и добавить параметр в уже объявленные конструкторы и подправить параметры Init, но мы теряем обратную совместимость библиотеки с другими решениями, которые вы возможно уже реализовали, либо используете сторонние решения основанные на этой библиотеке.
На этом этапе мы получаем рабочую библиотеку с необходимым нам функционалом. Настало время всё это протестировать на простом примере. Для этого откроем второй проект в решении, написанный на С# открываем файл App.cs и подправляем следующий фрагмент
LargeMessageQueue queue =
new LargeMessageQueue(queueFormatName);
на
LargeMessageQueue queue =
new LargeMessageQueue(queueFormatName, 3145728);
Теперь делаем полную сборку проекта, лучше всего предварительно сделать Build Clean.
На этом разработка заканчивается. Для теста создадим простое приложение BizTalk, котрое будет брать сообщение из очереди и складывать его в папку С:Demo.
- Создайте приватную очередь на локальном компьютере с именем Test, при создании необходимо выбрать параметр который указывает на поддержку очередью транзакций. Обязательно проверьте права на получение сообщений из этой очереди пользователем из под которого работает Ваш BizTalk Server
- Создайте папку С:Demo. Опять же обязательно проверьте права на зпись в папку для пользователя из под которого работает Ваш BizTalk Server
- 3. Откроем консоль администрирования Biztalk и создадим новое приложение, назовём его допустим MSMQBiztalkTest. В этом приложении создадим Send Port типа Static One-Way Send Port и назовём его MySendPort. Выбираем transport Type – FILE и соответственно настраиваем его, чтобы он складывал наши сообщения в папку C:Demo, которую мы ранее создали. Устанавливаем фильтр на этот порт со следующим значением BTS.ReceivePortName == MyReceivePort
- Создадим новый Receive Port типа One-way Receive Port и назовём его MyReceivePort. Для этого порта создадим новый Receive Locations типа One-way Receive Location с названием MSMQReceiveLocation. Выбираем Transport Type равным MSMQ и настраиваем на получение сообщений из нашей очереди для этого в настройках укажем Queue равной localhostprivate$test и установим Transactional в True.
- На этом тестовое BizTalk приложение создано, необходимо его запустить и перезапустить Biztalk сервис.
Для посылки сообщения в очередь используем приложение созданное нами ранее в VisualStudio 2010. Работает оно из командной строки и соответственно принимает два параметра параметры очереди и имя файла, который необходимо отправить.
SendLargeMessage.exe DIRECT=OS:localhostprivate$Test «C:TestDataLargeFile.xml»
В зависимости от размера файла вы сможете наблюдать его в каталоге C:Demo уже через несколько секунд и смотреть, как он постепенно растёт.
На этом всё. Если у кого-то возникли вопросы или пожелания с удовольствием отвечу на все в комментариях.
Источники:
Large Message to MSMQ
Автор: maxim_rubchenko