Интеграция решений на 1С и сервиса обмена данными RabbitMQ через Web REST API









Отправка «Hello world» из 1С на сервер RabbitMQ и обратно при помощи web REST API.
Проще уже некуда! Совместимо с Linux и Windows!
Реализация протестирована на 1С 8.3.14.1854 (x64).

WARNING

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

 

Описание:
В этой статье описан способ реализации интеграции с брокером сообщений RabbitMQ через веб интерфейс REST API.
На данный момент вендор не рекомендует использование веб-интерфейса в качестве основного протокола обмена, следующее сообщение можно встретить в мануалах по RabbitMQ:

Please note that the get path in the HTTP API is intended for diagnostics etc — it does not implement reliable delivery and so should be treated as a sysadmin’s tool rather than a general API for messaging.

Исходя из того, что вариантов для подключения и обмена данными с RMQ не так уж и много, а если вдруг у нас платформа на Linux — то вообще нет, считаю, что это выход. Также это единственный способ отправки сообщений предоставляющий возможность использовать маршрутизацию по "заголовкам".

Немного теории:

Сам по себе сервер RabbitMQ обычно не устанавливают. Почти всегда в дополнение ставят еще и модуль веб администрирования всего сервиса. Именно модуль администрирования имеет встроенное REST API, выступающее прослойкой между сервером AMQP и миром WEB.

Подробное описание REST API https://bulldog.rmq.cloudamqp.com/api/index.html

Итак, начнем:

Для тестирования API сделал обработку с одной командой — выполнить тестирование:

Здесь указаны настройки подключения к серверу:

Краткое описание работы:

  1. Создание подключения к веб серверу администрирования RabbitMQ;
  2. Создание базовой структуры параметров сообщения для отправки, исходя из REST API;
  3. Сериализация параметров в JSON;
  4. Отправка JSON в POST запросе на север RabbitMQ;
  5. Проверка удачной отправки сообщения;
  6. Подготовка параметров запроса для получения сообщения;
  7. Сериализация параметров запроса в JSON;
  8. Отправка JSON в POST запросе на сервер RabbitMQ;
  9. Обработка ответа сервера.

Код команды:

&НаСервере
Процедура ВыполнитьТестНаСервере()

// Cодать новое соединение с веб-сервером RabbitMQ
ИнтернетПрокси = Новый ИнтернетПрокси();
ЗащищенноеСоединениеOpenSSL = Новый ЗащищенноеСоединениеOpenSSL();
HTTPСоеинение = Новый HTTPСоединение(АдресСервера, Порт, ИмяПользователя, Пароль, ИнтернетПрокси, 360, ЗащищенноеСоединениеOpenSSL, Ложь);

////
//  Подготовим и отправим сообщение в RabbitMQ
////****************************************************//

// новое соответствие заголовков
// если обмен поддерживает адресацию по заголовкам то заполняем
// заполнять имя маршрута в таком случае не нужно
ЗаголовкиСообщения = Новый Соответствие;
Для Каждого СтрокаЗаголовок Из Заголовки Цикл
ЗаголовкиСообщения.Вставить(СтрокаЗаголовок.Ключ, СтрокаЗаголовок.Значение);
КонецЦикла;

// новые параметры сообщения
ПараметрыСообщения = Новый Структура("app_id, correlation_id, delivery_mode, content_type, headers");
ПараметрыСообщения.headers = ЗаголовкиСообщения;
ПараметрыСообщения.app_id = Метаданные.Синоним;  // кто отправил
ПараметрыСообщения.correlation_id = Строка(Новый УникальныйИдентификатор()); // уникальный идентификатор сообщения
ПараметрыСообщения.delivery_mode = 2; // где будет храниться сообщение 1 - оператива, 2 - диск
ПараметрыСообщения.content_type = "text/plain"; // тип содержимого

// структура отправки
СтурктураСообщения = Новый Структура("properties, routing_key, payload, payload_encoding");
СтурктураСообщения.properties = ПараметрыСообщения;
СтурктураСообщения.payload_encoding = "string"; // тип содержимого, по умолчанию строка
СтурктураСообщения.payload = Сообщение; // содержимое
СтурктураСообщения.routing_key = ИмяМаршрута;  // имя маршрута, пустое если заполнены заголовки сообщения

// сериализовать все параметры запроса в json
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, СтурктураСообщения);
СтрокаЗапроса = ЗаписьJSON.Закрыть();

// новый запрос REST API для RABBITMQ
ЗаголовкиЗапроса = Новый Соответствие;
ЗаголовкиЗапроса.Вставить("Content-Type", "application/json"); // тип содержимого - json
HTTPЗапрос = Новый HTTPЗапрос(СтрШаблон("/api/exchanges/%1/%2/publish", Хост, ИмяОбмена), ЗаголовкиЗапроса);
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаЗапроса);

// отправить сообщение в RabbitMQ POST запросом
HTTPОтвет = HTTPСоеинение.ОтправитьДляОбработки(HTTPЗапрос);

// если ошибка сообщим результат
Если HTTPОтвет.КодСостояния <> 200 Тогда
Сообщить(СтрШаблон("Код ответа: %1", HTTPОтвет.КодСостояния));
Сообщить(HTTPОтвет.ПолучитьТелоКакСтроку());
Возврат;
КонецЕсли;

////
//  Получим сообщение из RabbitMQ
////****************************************************//

// новая структура запроса сообщений из rabbitmq
СтурктураЗапроса = Новый Структура("count, ackmode, encoding, truncate");
СтурктураЗапроса.truncate = 10000000; // выгружать сообщения не превышающие этот размер в байтах
СтурктураЗапроса.encoding = "auto"; // содержимое какого типа мы хотим получить
СтурктураЗапроса.ackmode = "ack_requeue_false"; // удалить полученные сообщения
СтурктураЗапроса.count = 1;  // количество запрошеных сообщений

// сериализовать все параметры запроса в json
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, СтурктураЗапроса);
СтрокаЗапроса = ЗаписьJSON.Закрыть();

// новый запрос REST API для RABBITMQ
ЗаголовкиЗапроса = Новый Соответствие;
ЗаголовкиЗапроса.Вставить("Content-Type", "application/json"); // тип содержимого - json
HTTPЗапрос = Новый HTTPЗапрос(СтрШаблон("/api/queues/%1/%2/get", Хост, ИмяОчереди), ЗаголовкиЗапроса);
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаЗапроса);

// Получить сообщения из RabbitMQ ответом на POST запрос
HTTPОтвет = HTTPСоеинение.ОтправитьДляОбработки(HTTPЗапрос);

// если ошибка сообщим результат
Если HTTPОтвет.КодСостояния <> 200 Тогда
Сообщить(СтрШаблон("Код ответа: %1", HTTPОтвет.КодСостояния));
Сообщить(HTTPОтвет.ПолучитьТелоКакСтроку());
Возврат;
КонецЕсли;

// Прочитаем ответ сервера
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(HTTPОтвет.ПолучитьТелоКакСтроку());
СтурктураHTTPОтвета = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();

// выделим содержимое сообщения
Ответ = СтурктураHTTPОтвета[0].payload;

КонецПроцедуры

Производительность решения:

Действие Количество Время Объем Комментарий
Отправка 1000 1 минута 1335 байт каждое сообщение В качестве сообщений взят
Lorem ipsum из вики
Прием 1000 3 секунды 1335 байт каждое сообщение

 

Вывод: это самый простой способ обмениваться сообщениями с RabbitMQ, используя исключительно встроенные возможности 1С Предприятие, которые доступны во всех версиях платформы.

12 Comments

  1. Region102

    Наконец-то можно будет затестить с мобильной платформой. Как раз клиент интересовался по поводу высоконагруженной системы, до 10 000 запросов в час. А то я не уверен, что http сервис 1С это выдержит.

    Reply
  2. user1166203

    (1)

    3 запроса в секунду? Ну, в пике 10-20. Странные у вас сомнения 🙂

    Reply
  3. yaroslavkravets

    Rest API RMQ не имеет гарантии доставки. для того чтобы затестить — подойдеть. но для большого проекта нужно смотреть в сторону amqp

    Reply
  4. Eret1k

    (3)где именно в технической документации вендора написано, что нет гарантии доставки?

    Reply
  5. yaroslavkravets

    (4) https://www.rabbitmq.com/management.html#http-api-monitoring

    The API is intended to be used for monitoring and alerting purposes. It provides access to detailed information about the state of nodes, connections, channels, queues, consumers, and so on.

    Reply
  6. yaroslavkravets

    Для получения данных из очереди нужно спрашивать кролик — есть ли изменения?

    Reply
  7. Region102

    (2) а кто сказал, что нагрузка будет распределенной во времени. Там может и за минуту столько быть, а может и за час 2-3 запроса. Вопрос отказоустойчивости системы, при этом каждый запрос должен создать и провести по регистрам типовой документ, сможет это 1С или нет, вот в чем вопрос.

    Reply
  8. Eret1k

    (6) да нужно, делаем регламентное задание и каждые к примеру 5 минут опрашиваем, есть ли сообщения.

    Reply
  9. Eret1k

    (5) это просто предупреждение и о нем Я писал выше.

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

    Естественно web это не потянет, но при обмене сотней другой сообщений с короткими перерывами это самое то.

    Reply
  10. Feelthis

    На моем опыте среди клиентов для Rabbit MQ на Node js — самый эффективный. Особенно если у вас высоконагруженный проект. Если к примеру мы читаем из Rabbit в сторону 1С (подключаемся по http сервисам), далее данные просто сохраняем в справочник, то клиент на node может считать и загрузить 100-150 сообщений в сек. Клиентом на C# мне не удалось такого достичь (не знаю есть ли там асинхронность не силен в C#). Использовать Web REST API вряд ли подойдет для скорости..

    «Исходя из того, что вариантов для подключения и обмена данными не так уж и много, а если вдруг у нас платформа на Linux — то вообще нет, считаю, что это выход» — вот тут вообще не понял что хотели сказать в статье.

    Reply
  11. starik-2005

    (10)

    то клиент на node может считать и загрузить 100-150 сообщений в сек

    Вот тут некто пишет, что достигал куда более весомого результата обычным курлом вроде как…Может быть в железяге дело.

    С другой тороны, я на REDIS’е, который тоже умеет очереди, через именованные каналы даже на пыхе получал в районе 100к запросов в секунду… Но это райзен 1600-й, а не пентиум голд, конечно…

    Reply
  12. Feelthis

    (11)

    Имею ввиду, что при замере я включил время записи 1с данных в справочник (чисто запись без всяких проверок) и то что клиент ждет ответ от 1с — успешно ли данные записались. То есть в call back функции обрабатываем ответ, в случае успеха делаем acknowledge, в случае не успеха — обрабатываем ошибки от 1с (например база на обслуживании и прочее) и делаем reject.

    Понятно если просто читать сообщения там скорость космическая. Также в случае если мы всегда авто подтверждаем сообщения (без всяких проверок в callback ответах) то скорость тоже будет намного выше.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *