Здравствуйте.
Описанные ниже мысленные изыскания были навеяны статями сильвер булетов и прочих товарищей по использованию очередей на основе RabbitMQ. Описывать, что, как и зачем использовать этот брокер мессенджер не вижу смысла — в предыдущих статьях все хорошо описано. Здесь я опишу сугубо практику применения.
Причина использования очередей — зоопарк систем на новом месте работы, обменивающихся друг с другом информацией всевозможными спосособами. Как правило, способами медленными не информативными и отнимающими тонны рабочего времени отдела на собственную поддержку.
Основной обмен происходил файлами через файлопомойку без какого-либо оповещения об обработке входящих данных и т.п. Зачастую получалась ситуация, что данные отправлены, что-то пошло не так, данные не получены системой получателем, но система отправитель об этом ни сном ни духом. В результате получаем бесконечный поток писем в поддержку "Где наши платежи/заказы/etc?! В рознице деньги оприходовали/заказ провели,, а на сайт они не попали" и т.п. На диагностику проблемы уходило безумное количество времени, потому что, чтобы понять причину сотрудник поддержки:
- Смотрел лог отправки в системе отправителе.
- Проверял, что файла нет в папке получателе. (данные не стоят в очереди)
- Проверял, что файл есть в архивной папке системы получателя (данные получены и обработаны)
- Проверял данные самого файла.
- Проверял логику формирования данных.
И это на каждое письмо. Теперь:
- Открывает лог отправки данных в системе отправителе и смотрит в нем все статусы пакета данных (дата отправки, дата получения, ссылка на текст отправленных данных).
- Проверяет логику формирования данных.
В итоге получаем значительную экономию времени. Думаю, у каждого таких примеров наберется немало.
Итак, выбор пал на RabbitMQ (далее, Кролик). К сожалению, я не обнаружил сразу описания HTTP интерфейса Кролика, а на глаза попала библиотека для C# на самом сайте Кролика. Было решено в исследовательских целях написать COM-компоненту на коленке и небольшой сервис (службу) для обслуживания входящих сообщений и направлений их к адресату.
Компоненту можно регистрировать, как 32, так и 64 битную, зависит от того, какой версией регасма будете регистрировать. В итоге для работы сервера с ней нет необходимости оборачивать ее в COM+. Регистрация компоненты проходит regasm’ом, а не regsvr32:
64 бита:
C:WindowsMicrosoft.NETFramework64v4.0.30319
egasm /codebase <Путь к файлу компоненты>
32 бита:
C:WindowsMicrosoft.NETFrameworkv4.0.30319
egasm /codebase <Путь к файлу компоненты>
Не знаю, обязателен ли ключ /codebase, но я регистрировал с ним. Версию .NET фреймворка используйте последнюю свою.
Использование компоненты отправки сообщений в 1С:
Объект = НОВЫЙ COMОбъект("AMQPSend.COM"); //Создаем COM объект
Объект.Connect(ИмяСервераКролика, Логин, Пароль);// Подключаемся к серверу Кролика
Результат = Объект.Send(ИмяУзла, КлючМаршрутизации, СтрокаДанных); //Отправляем данные
Объект.Close();//Закрываем соединение к серверу Кролика
У объекта только одна функция Send. Имя узла — Exchange Кролика, КлючМаршрутизации — routingKey, СтрокаДанных — строковое представление передаваемых данных.
В случае успешной технической отправки данных функция возвращает "0", либо описание исключения в случае технической неудачи. Проверки прав на помещение данных в указанный узел у пользователя, под которым компонента подключилась к Кролику не писал.
Таким образом, отправлять 1С данные в Кролика указанному получателю мы научились. Далее пришло время получать это все оттуда. Так же на C# была написана простенькая служба, которая создает подписчиков на определенные ключи маршрутизации в определенных узлах и переправляет эти данные получателям.
Установка службы:
C:WindowsMicrosoft.NETFramework64v4.0.30319installutil <Путь к exe файлу службы>
Удаление
C:WindowsMicrosoft.NETFramework64v4.0.30319installutil /u <Путь к exe файлу службы>
Получателям 1С служба умеет отправлять данные двумя способами — в HTTP-сервис или в Web-сервис. Служба может поднимать множественное количество подписчиков на разные ключи маршрутизации и узлы, переправляя данные в http и/или web-сервис.
Пример конфигурационного файла (находится в папке с экзешником)
<consumers>
<consumer>
<host>[Имя сервера Кролика]</host>
<routingKey>[Ключ маршрутизации]</routingKey>
<exchange>[Узел Кролика]</exchange>
<httpUrl>[URL для переправки данных]</httpUrl>
<soapUrl>[URL для POST запроса в WEB-сервис]</soapUrl>
<soapAction>[Функция, вызываемая в WEB-сервисе]</soapAction>
<user>[Пользователь Кролика]</user>
<password>[Пароль пользователя Кролика]</password>
<prefetchCount>[Число сообщений, считываемых службой из очереди Кролика]</prefetchCount>
<soapUrlExample>http://domain.com/base/ws/ESBExchange</soapUrlExample>
<soapActionExample>http://domain.com/base/ws/ESBExchange/UploadData</soapActionExample>
</consumer>
</consumers>
Credentials для запросов в 1С не ставил, т.к. у меня предполагается отправка все внутри сети. prefetchCount — это уже начались игры разума по вопросам распараллеливания переправки сообщений в 1С. Поднимать несколько подписчиковна одну очередь или забирать в экземпляр слушателя несколько сообщений и распараллеливать в нем — дальше бесконечное поле для ускорения и т.п. prefetchCount определяет сколько сообщений забирает на обработку подписчик себе из очереди Кролика.
В моем случае в одну очередь в день попадет до 30к сообщений — последовательно они все успешно отрабатывают, потому я оставляю этот параметр равный 1. Без создания тасков внутри подписчика увеличение данного числа ничего не даст.
Дополнительно настраивается еще один файл SOAPquery.txt:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:ns="ns">
<soap:Header/>
<soap:Body>
<ns:UploadData>
<ns:Data>%data%</ns:Data>
</ns:UploadData>
</soap:Body>
</soap:Envelope>
В этот файл я добавил шаблон запроса в Web-сервис. Некрасиво, но удобно. Находить удобные библиотеки для работы с SOAP мне было лень. Текст %data% в шаблоне заменяется на передаваемые текстовые данные, потому лучше заворачивайте их в строку Base64, чтобы не заниматься экранированием и прочими радостями. Формат файла удобно получить из SoapUI, скормив ему WSDL вашего сервиса.
Конфиг файл и шаблон SOAP запрос мы настроили, можно запускать службу. Служба при старте создаст столько подписчиков, сколько сконфигурируете в конфиге, подписчики подключаться к узлам, Создадут временные очереди, привязанные к указанным ключам маршрутизации и начнут переправлять данные.
Теперь прием сообщения в 1С:
[Блок получения данных в HTTP/WEB сервисе]
[Парсинг данных и необходимые действия]
Объект = НОВЫЙ COMОбъект("AMQPSend.COM");
Объект.Connect(ИмяСервераКроликаДляОтвета, Логин, Пароль);
Результат = Объект.Send(ИмяУзлаДляОтвета, КлючМаршрутизацииДляОтвета, ДанныеСОтветом);
Объект.Close();
В начале производим все необходимые данные в соответствии с логикой загрузки. Далее из входящих данных получаем идентификатор, данные Кролика этого пакета данных (мы ведь их передаем вместе с данными, верно?) и передаем точно так же обратно в Кролик. Теперь наша передача сообщения в другую систему выглядит как:
- Система 1 формирует передаваемый пакет, дополняя его данными для отправки уведомления о доставке.
- Система 1 отправляет его в очередь Системы 2.
- Система 2 принимает пакет из очереди и обрабатывает его.
- Система 2 отправляет подтверждение в очередь, настройки которой пришли во входящем пакете.
Таким образом, обеим системам неважно, кто и каким образом отправляет сообщение (если это важно для бизнес-логики, то эта обработка будет на стороне каждой из систем на основании входящих данных). Схема чрезвычайно легко масштабируется. В очередь/узел Системы 2 могут посылать сообщения любые другие системы и ответ в эти системы будет точно таким же, как и в Систему 1.
Так что пробуйте, видоизменяйте, унифицируйте.
К публикации приложены как есть:
- COM компонента для отправки сообщения из 1С
- Служба подписчиков
- Исходники и того, и другого.
Экономика:
Потрачено — 5 вечеров свободного времени.
Получено — высвобождение 3-4 человеко часа в день, что в условиях кадрового дефицита — бесценно 🙂
PS Заранее предупрежу — я не .NET разработчик. Писал все на знаниях, оставшихся после института, и туториалах из интернета. Достигать максимального уровня абстракции не собирался. Все выложено исключительно для пробных шагов в этом направлении остальных участников сообщества. Код открыт — можно и нужно модифицировать, как угодно.
Я бы все-таки обратил внимание на разграничение доступа. Нужна хотя бы минимальная защита. Любая копия базы, снятая с рабочей, начнет слать в рэббит «левые» сообщения. Сэкономленные человеко-часы будут перечеркнуты «случайными» отправками платежных документов из баз разработчиков.
(1)
Ну, это уже на уровне кода конфигураций контролировать. Либо ключи маршрутизации создавать вида <Строка базы 1><Строка базы 2>, или наплодить несколько узлов с именами Система отправителя в виде строк этих баз, и оттуда уже ключами маршрутизации перенаправлять в узел получателя. Простор для творчества.
А еще лучше не регистрировать компоненту на сервере разработчиков 🙂
(4)
Вы не должны
(3) граммар наци живёт в ЖЖ. проследуйте туда.
Приветствую!
К Вашей цитате:
Не могли бы пруфом поделиться? Спасибо!
(7)
Пожалуйста
(8) ой не, HTTP-API это прям совсем медленно, тем более, что по ссылке — администраторский API. Да, он позволяет отправлять, но это костылище. Используйте родных клиентов, работающих по протоколу AMQP. Например, наш <скрытая реклама детектед> 🙂
(9) дело в управлении этим хранилищем файлов. Рано или поздно, автоматизируя папку обмена и настраивая к ней доступ, вы напишете сервер очередей. Так может сразу начать с него?
(3) Бывает же…
(11) На этапе когда нужен обмен между двумя базами — сервер очередей избыточен.
В описанном примере это именно такой случай — из-за применения Раббита осталось только еще больше не проработанных вопросов, которые до этого при обычном файловом обмене были решены. То есть мы существенно увеличили сложность решения (отдельный сервер очередей, внешние компоненты для обмена, ХТТП-сервис), функциональность та же, а качество хуже.
Rabbit — не серебрянная пуля:)
Я не рассматриваю случаи когда у нас сотни потребителей, распаралеленные очереди, несколько серверов очередей связанных между собой и разнородные среды для интеграции — тогда да я обеими руками за Раббит)
у кого-то есть готовая компонента для раббита ?
(14)
Прикреплена к статье вместе с исходниками.
Правильно понимаю, что в основном это применяется для разработки сервисных шин данных? ESB?
Где еще можно применить связку?
(16)
Например, распределение пиковой нагрузки. Пришло вам 100500 запросов в секунду и веб-сервер отказался работать. Засунули эти 100500 в очередь, сами указали сколько потоков параллельно обрабатываются из Кролика и в колбэк функцию вернули результаты запроса.
(17) ясно. спасибо за пример.
(0) ActiveMQ имеет встроенный REST API 🙂
Вовсе необязательно подсовывать кролика где ни попадя.
А можно как то подписаться на события кролика?
(20)
Дописывать / Переписывать приложенную службу.
(21) не реализовано, понял, но вот в чем вопрос, как в контексте сервера можно подписаться на события, это не регламентное задание где периодически что то вызывается, все, а иметь запущенного клиента тоже не очень хорошо… у меня варианты кончились )
(22)
Не понимаю вашей боли. Давайте пример, чтоли, что вы хотите получить.
(23) хочу обработать события по конкретному каналу из кролика, как это сделать в контексте севера 1С, без запущенных клиентов 1С.
(24)
При получении сообщения служба посылает http-запрос по указанному вами адресу. Клиентов никаких загружать не надо. Или вы под событиями понимаете что-то иное?
(25) я сейчас не говорю про http, его нет, есть RabbitMQ, как 1С может получать данные из какой то очереди, при их появлении.
(26)
Эм. Вы ведь прочитали публикацию?
Не можете поднять веб-сервер, допишите службу, пусть напрямую в СКЛ пушит данные или КОМ-соединение поднимает и в него пуляет.
(26) Обрати внимание на платную компоненту
https://silverbulleters.org/rabbitmq
Серьезно и быстро
(28) Работает напрямую с Реббитом через нативную компоненту 1С
(27) я читал, и все понял, и задал вопрос, может не по конкретной это теме но это про очереди+1с в целом, как решить вопрос я знаю, просто хочется послушать мысли умных людей по этому вопросу 🙂
(29) спасибо за ссылку, не вариант
(10) Коллега, можно подробней плз, за счет чего прямые HTTP-запросы из 1С к RMQ медленнее вашей ВК? Сравнительные замеры проводили?
Добрый день.
При подключении к серверу кроля с сервера (Windows server 2008 R2) выдаёт ошибку — {ВнешняяОбработка.ПостановкаВОчередьКролика.МодульОбъекта(27)}: Ошибка при вызове метода контекста (Connect): Произошла исключительная ситуация (AMQPSending): Не удалось загрузить файл или сборку «RabbitMQ.Client, Version=5.0.0.0, Culture=neutral, PublicKeyToken=89e7d7c5feba84ce» либо одну из их зависимостей. Не удается найти указанный файл.
Подключение с компа с Windows 7 работает.
Не подскажите направление — в чем может быть проблема ?
А где в конфиг файле указывается лого пасы web-сервиса?
Коллеги, объясните мне убогому пожалуйста.
Правильно я понимаю: Когда на Кролик приходит некое сообщение оно переправляется слушателю.
Слушать пусть будет вебсервис 1С. я не понимаю где я должен указать логин и пароль вебсервиса 1С чтобы кролик в него послал это некое сообщение.
webClient.Headers.Add(«Authorization: Basic», «логин:пароль»); логин:пароль от 1С нужно в басе64
или
soapRequest.Headers.Add(«Authorization: Basic», «логин:пароль»);
в зависимости от того что вы используете, http или soap
или
можете самостоятельно добавить в файл Consumers.xml в тег Consumer пару полей user1c и password1c.
добавить их же в класс MyConsumer и в его конструктор.
добавить в ServiceMQConsumer в методе InitialiazeConsumers их заполнение.
при отправке запроса в хеадер добавлять логин и пасс из конкретного экземпляра mqConsumer
С хеадерами правильно вот так:
и