RabbitMQ нативно в 1С: без компонент, прокси и шины

30.03.26

Разработка - Механизмы платформы 1С

В этой статье мы рассмотрим, как заставить 1С напрямую общаться с RabbitMQ, получив при этом outbox/inbox "из коробки" без сторонних библиотек и прокси-сервисов.

RabbitMQ нативно в 1С:
без компонент, прокси и шины

 

Как заставить 1С напрямую общаться с RabbitMQ, получив outbox/inbox «из коробки» без сторонних библиотек и прокси-сервисов

Эта статья была написана по просьбе одного из наших с вами коллег. Евгений, привет!

Что, если работать с RabbitMQ можно практически нативно средствами самой платформы — и при этом получить уже готовые реализации паттернов outbox и inbox почти безболезненно?

Звучит как что-то невероятное, но способ существует.
Я предполагаю, что у тебя, дорогой читатель, уже есть опыт работы с RabbitMQ или как минимум понимание того, что это такое и какие преимущества он даёт. В этой статье я не буду объяснять, как строить топологию брокера, разбирать виды обменников или способы ответов на сообщения, её цель — показать, что взаимодействовать с RabbitMQ можно нативно, используя только средства самой платформы.

Существующие подходы и их компромиссы

На данный момент мне известно несколько способов прикрутить RabbitMQ к 1С, разной степени боли и жести

Способ Проблема
Внешние компоненты Утечки памяти, ограничения концепции фоновых заданий вроде зависаний и необходимости повторной инициализации библиотек
Прокси-сервис В лучшем случае это long polling. Дополнительная точка отказа, на которой тоже нужна буферизация хотя бы с помощью sqlite
протоколы MQTT / STOMP Сложная реализация, часть возможностей AMQP недоступна. STOMP вообще простой текстовый протокол, MQTT ограничен в семантике
CDC (Debezium) Debezium не умеет в RabbitMQ напрямую а Debezium Server требует отдельного инстанса на каждую базу данных
1С:Шина Требует инфраструктуры, изучения, поддержки но именно её существование делает описанный метод возможным

Немного теории: как платформа работает с 1С:Шиной

Для работы с 1С:Шиной платформа использует объект метаданных «Сервисы интеграции». Он предоставляет удобный функционал отправки и обработки сообщений, хранит несколько таблиц в базе данных и реализует паттерн Outbox, а также уникальные ключи сообщений для обеспечения идемпотентности.

Что у них общего?
Внезапно и Сервисы интеграции, и 1С:Шина работают поверх протокола AMQP 1.0 — того же, который поддерживает RabbitMQ. Это и есть наш способ пообщаться.

Как платформа получает список каналов

Чтобы использовать сервис интеграции, сначала нужно создать или загрузить каналы. В форме загрузки указывается адрес 1С:Шины, а дальше платформа делает два последовательных HTTP-запроса:

Платформа отправляет запрос на /auth/oidc/token с заголовком Authorization: Basic <login:password в base64> и ожидает ответ такого вида:

JSON ожидаемый ответ /auth/oidc/token
{
  "id_token": "<ваш токен>",
  "token_type": "Bearer",
  "access_token": "Not implemented"
}

Шаг 2 — Получение списка каналов

Получив токен, платформа запрашивает GET /sys/esb/metadata/channels уже с заголовком Authorization: Bearer <токен>. В ответ она ожидает список каналов:

JSON формат ответа /sys/esb/metadata/channels
[
  {
    "process": "Основной::Обмен",
    "processDescription": "",
    "channel": "toShop",
    "channelDescription": "",
    "access": "WRITE_ONLY"
  },
  {
    "process": "Основной::Обмен",
    "processDescription": "",
    "channel": "fromShop",
    "channelDescription": "",
    "access": "READ_ONLY"
  }
]
В обычной ситуации эти данные приходят из шины.
В нашем же случае — можно отправить что угодно. Имена process и channel — просто строки, позволяющие связать каналы конфигурации с каналами получаемыми в рантайме.

Наша ягодка — поле destination

Когда платформа начинает фактически отправлять сообщение, она делает ещё один запрос для получения токена, и ещё один для получения списка каналов, но уже на GET /sys/esb/runtime/channels. Однако она получает не просто список каналов, а адреса и порт для переключения на AMQP 1.0:

JSON формат ответа /sys/esb/runtime/channels (от 1С:Шины)
{
  "items": [
    {
      "process": "e1c::ТестовыйПроект::Основной::OfficeToShop",
      "channel": "toShop",
      "destination": "PUBLIC.VGVzdEFwcA==.-1.d34871...toShop.shop"
    }
  ],
  "port": 6698
}

destination — это адрес, по которому платформа будет адресовать сообщения после переключения на AMQP. В случае шины там закодированная base64 + md5 строка с внутренними идентификаторами. Но нас это не смущает, ведь мы можем указать там любой адрес— а именно тот, который понимает RabbitMQ.

А как RabbitMQ маппит адреса AMQP 1.0 на свои собственные?

Ты, дорогой читатель, удивишься, но RabbitMQ при включённом плагине amqp 1.0 имеет специальные форматы адресации которые, вот ведь неожиданность, очень удобно использовать:

AMQP address форматы маршрутов RabbitMQ
// Отправка на обменник с routing key
/exchanges/<exchange_name>/<routing_key>

// Чтение из очереди напрямую
/queues/<queue_name>

Вот и вся магия: подставляем в destination маршрут в формате RabbitMQ и указываем порт самого брокера (5672). Платформа переключается на AMQP-соединение и общается с кроликом так, будто общается с 1С:Шиной.
JSON наш ответ /sys/esb/runtime/channels → RabbitMQ
{
  "items": [
    {
      "process": "rabbitmq",
      "channel": "write_channel",
      "destination": "/exchanges/1c_exchange/some.external.service"
    },
    {
      "process": "rabbitmq",
      "channel": "read_channel",
      "destination": "/queues/read.queue"
    }
  ],
  "port": 5672
}
Кстати, клиенты, использующие AMQP 0.9.1, продолжают работать как обычно — те же очереди и обменники, никаких конфликтов, все ок :)

Практика

Мы поняли, как общаться с RabbitMQ из 1С. Осталось реализовать это на практике.
Вариантов может быть множество — от нормальной реализации с OAuth провайдерами, отдельным сервисом раздачи каналов, настроенной авторизацией на RabbitMQ до раздачи статики вебсервером.

Но я же обещал максимально нативно — поэтому мы реализуем HTTP-сервисы, так ещё и без OAuth (хотя платформа позволяет настроить авторизацию с токеном).

Шаг 1. Поднимаем RabbitMQ

Поднимаем RabbitMQ с плагином management UI. Если версия брокера ниже 4.0 — включаем плагин AMQP 1.0 командой:

Shell
rabbitmq-plugins enable rabbitmq_amqp1_0

Начиная с RabbitMQ 4.0 протокол AMQP 1.0 поддерживается нативно

В панели управления создаём обменник, я назову его 1c_exchange.

 

Отмечу, что использовать _ в именах очередей, обменников и ключей привязки всё же не стоит. В примере он оставлен только ради наглядности.

Создаём очередь test и привязываем её к обменнику. Для каждой очереди важно создавать привязки — именно это позволяет отправителю не знать о получателе, а получателю использовать, например, заголовок replyTo.

 

Вообще, как правило, point-to-point обмен, когда отправитель знает детали адреса получателя (имя базы) — плохая затея. Назначайте роуты по ИНН организаций, скажем, и вычисляйте в процессе работы.

Если все сделано правильно, то список привязок будет выглядеть вот так:


 

Для получения сообщений создаём отдельную очередь read.queue и также привязываем её к тому же обменнику с маршрутом some.internal.service - другие системы будут писать именно через него:

 

 

Шаг 2. HTTP-сервис на стороне 1С

Нам нужен HTTP-сервис с тремя маршрутами:

POST/auth/oidc/token GET/sys/esb/metadata/channels GET/sys/esb/runtime/channels

Решаем проблему авторизации

Здесь есть нюанс: при загрузке каналов платформа сначала авторизуется через Basic (логин и пароль в Base64), а потом переходит на Bearer <токен>. HTTP-сервис 1С без дополнительной настройки для авторизации по токену вернёт ошибку на Bearer-запрос.

Но нас это не пугает — в ответе /auth/oidc/token возвращаем token_type: "Basic" и кладём в id_token ту же Base64-строку логина и пароля, которую получили в заголовке запроса. Тогда все дальнейшие запросы платформа будет подписывать Authorization: Basic <base64> — и сервис их примет, и RabbitMQ в дальнейшем не обидится.

Почему это важно: при AMQP-подключении 1С передаёт токен из заголовка в поля user и password механизма SASL. Если OAuth-плагин RabbitMQ не настроен, брокер ищет пользователя с такими реквизитами — поэтому мы создадим его заранее.

Подготовка пользователя:

  1. 1 Создаем пользователя в 1С, например: логин Admin, пароль test.
  2. 2 Закодируем строку Admin:test в Base64 — получится QWRtaW46dGVzdA==.
  3. 3 Создаем пользователя в RabbitMQ с именем QWRtaW46dGVzdA== и паролем QWRtaW46dGVzdA== — они одинаковые.

 

Код HTTP-сервиса (1С)

Создаём три обработчика — по одному на каждый маршрут:

 

 

И добавляем в обработчики следующий код:

1C POST /auth/oidc/token — выдача токена
Функция АвторизацияЗапросТокена(Запрос)
    Ответ = Новый HTTPСервисОтвет(200);

    // Берём Base64-строку прямо из заголовка запроса
    СтрокаАвторизации = Запрос.Заголовки.Получить("Authorization");
    СтрокаАвторизации = СтрЗаменить(СтрокаАвторизации, "Basic ", "");

    Ответ.УстановитьТелоИзСтроки(
    "{
    |  ""id_token"": """ + СтрокаАвторизации + """,
    |  ""token_type"": ""Basic"",
    |  ""access_token"": ""Not implemented""
    |}");

    Возврат Ответ;
КонецФункции
1C GET /sys/esb/metadata/channels — список каналов
Функция КаналыМетаданныеЗапросКаналов(Запрос)
    Ответ = Новый HTTPСервисОтвет(200);
    Ответ.Заголовки.Вставить("Content-type", "application/json; charset=utf-8");

    Ответ.УстановитьТелоИзСтроки(
    "[
    |  {
    |    ""process"": ""RabbitMQ"",
    |    ""processDescription"": """",
    |    ""channel"": ""write_channel"",
    |    ""channelDescription"": """",
    |    ""access"": ""WRITE_ONLY""
    |  },
    |  {
    |    ""process"": ""RabbitMQ"",
    |    ""processDescription"": """",
    |    ""channel"": ""read_channel"",
    |    ""channelDescription"": """",
    |    ""access"": ""READ_ONLY""
    |  }
    |]");

    Возврат Ответ;
КонецФункции
1C GET /sys/esb/runtime/channels — маршруты RabbitMQ
Функция КаналыРантаймЗапросКаналов(Запрос)
    Ответ = Новый HTTPСервисОтвет(200);

    Ответ.УстановитьТелоИзСтроки(
    "{
    |  ""items"": [
    |    {
    |      ""process"": ""RabbitMQ"",
    |      ""channel"": ""write_channel"",
    |      ""destination"": ""/exchanges/1c_exchange/some.external.service""
    |    },
    |    {
    |      ""process"": ""RabbitMQ"",
    |      ""channel"": ""read_channel"",
    |      ""destination"": ""/queues/read.queue""
    |    }
    |  ],
    |  ""port"": 5672
    |}");

    Возврат Ответ;
КонецФункции

Публикуем HTTP-сервис на веб-сервере.

Шаг 3. Настройка обратного прокси (Apache)

Платформа обращается к маршрутам напрямую от адреса сервера, то есть без наших base/hs/etc. Нам нужно перенаправить запросы на эти адреса на наш HTTP-сервис.

Для Apache в файле conf/extra/httpd-vhosts.conf добавляем виртуальный хост с обратным прокси:

Apache httpd-vhosts.conf
<VirtualHost *:80>
    ServerName localhost

    ProxyPass        /auth/oidc/token
                     http://localhost/test/hs/channels/auth/oidc/token
    ProxyPassReverse /auth/oidc/token
                     http://localhost/test/hs/channels/auth/oidc/token

    ProxyPass        /sys/esb/metadata/channels
                     http://localhost/test/hs/channels/sys/esb/metadata/channels
    ProxyPassReverse /sys/esb/metadata/channels
                     http://localhost/test/hs/channels/sys/esb/metadata/channels

    ProxyPass        /sys/esb/runtime/channels
                     http://localhost/test/hs/channels/sys/esb/runtime/channels
    ProxyPassReverse /sys/esb/runtime/channels
                     http://localhost/test/hs/channels/sys/esb/runtime/channels
</VirtualHost>

В основном httpd.conf раскомментируйте нужные строки:

Apache httpd.conf — включаем модули
LoadModule proxy_module      modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
Include    conf/extra/httpd-vhosts.conf

Если у тебя, читатель, nginx — настройка proxy_pass значительно проще и займёт где-то пару строк в location.
Ну а я могу только позавидовать :)

Шаг 4. Загрузка каналов

Открываем форму загрузки каналов, указываем адрес нашего сервера, логин и пароль пользователя 1С. Нажимаем «Получить каналы» — каналы появятся в дереве метаданных конфигурации.


 

Для канала чтения добавляем обработчик входящих сообщений:

1C обработчик входящего сообщения read_channel
Процедура RabbitMQ_read_channelОбработкаПолученияСообщения(Сообщение, Отказ)
    Поток = Сообщение.ПолучитьТелоКакПоток();

    Буфер = Новый БуферДвоичныхДанных(Сообщение.РазмерТела);
    Поток.Прочитать(Буфер, 0, Сообщение.РазмерТела);

    Сообщить(ПолучитьСтрокуИзБуфераДвоичныхДанных(Буфер, КодировкаТекста.UTF8));
КонецПроцедуры

Обновляем конфигурацию, переходим в управление сервисами интеграции, активируем сервис и указываем логин/пароль пользователя — того же, которого мы создали, именно его base64 строка будет передана в RabbitMQ.


 

Шаг 5. Отправка сообщения из 1С → RabbitMQ

Итак, мы на финишной прямой, пора попробовать отправить сообщение — создайте обработку, на форме добавьте поле «Сообщение», команду «Отправить» и в обработчик вставьте этот код:

1C отправка сообщения через сервис интеграции
Процедура ОтправитьНаСервере()
    БуферСообщения = ПолучитьБуферДвоичныхДанныхИзСтроки(ЭтотОбъект.Сообщение);

    // Создаём сообщение через сервис интеграции
    СообщениеИнтеграции = СервисыИнтеграции.RabbitMQ.СоздатьСообщение();

    ПотокСообщения = СообщениеИнтеграции.ПолучитьТелоКакПоток();
    ПотокСообщения.Записать(БуферСообщения, 0, БуферСообщения.Размер);
    ПотокСообщения.Закрыть();

    // Сохраняет сообщение в БД (Outbox-паттерн)
    СервисыИнтеграции.RabbitMQ.proc_write_channel.ОтправитьСообщение(СообщениеИнтеграции);

    // Запускает фоновое задание отправки
    // какое-то время оно будет обрабатывать входящие и исходящие сообщения
    СервисыИнтеграции.ВыполнитьОбработку();
КонецПроцедуры

Жмем на заветную кнопку



и... 

 

Соединение установлено! Отлично, а что у нас в очереди some.external.service?


 

Получилось! В очереди хранится сообщение, в payload - отправленный нами текст, закодированный в формате base64. Осталось только получить сообщение ИЗ очереди.

Шаг 6. Получение сообщения из RabbitMQ → 1С

Переходим в панель RabbitMQ, открываем очередь read.queue и публикуем тестовое сообщение прямо в неё.

 

Любым способом вызовите метод СервисыИнтеграции.ВыполнитьОбработку(), можно через ту же обработку, и...

 

Поздравляю! Вы великолепны.

Что в итоге

Мы только что отправили и получили сообщения из RabbitMQ средствами самой платформы 1С. Никаких внешних компонент, никакого прокси-сервиса, никакой шины. Как я и обещал.

Вся настройка сводится к трём вещам:

  1. 1 Реализовать три HTTP-эндпоинта, которые прикинутся 1С:Шиной
  2. 2 Подставить в destination маршрут в формате RabbitMQ и нужный порт
  3. 3 Создать в RabbitMQ пользователя с реквизитами в формате Base64

Инструменты для отправки, хранения (Outbox), обработки и идемпотентности предоставляет сама платформа. В реальном проекте имеет смысл добавить провайдер авторизации и вынести конфигурацию каналов в отдельный управляющий сервис, но в целом механика остаётся той же.

Нюансы есть, например, мы не можем использовать другой vhost, а динамическая маршрутизация может вызывать сложности.
Однако для большинства задач, связанных с 1С, хватит и этого, ведь для других клиентов использование AMQP 0.9.1 остается тем же.
Всё же я считаю, что выгоды этого метода превышают любые недостатки, если сравнивать с альтернативами.

Вот и всё. Надеюсь эта статья вам поможет, с вами был
@okniceman

Вступайте в нашу телеграмм-группу Инфостарт

См. также

Механизмы платформы 1С Программист Бесплатно (free)

Разберем 15 мифов о работе платформы «1С:Предприятие 8» – как распространенных, так и малоизвестных. Начнем с классики: «Код, написанный в одну строку, работает быстрее, чем многострочный». Так ли это на самом деле?

16.07.2025    30515    TitanLuchs    106    

149

Механизмы платформы 1С Работа с интерфейсом Программист Стажер 1С:Предприятие 8 Бесплатно (free)

Про ООП в 1С и о том, как сделать свой код более кратким и выразительным при помощи использования текучего интерфейса (fluent interface).

03.02.2025    16696    bayselonarrend    127    

68

Механизмы платформы 1С Программист 1С:Предприятие 8 Бесплатно (free)

В этой статье подробно рассматривается работа с JSON в XDTO в 1С:Предприятие. Вы узнаете, как сериализовать и десериализовать объекты XDTO в JSON, интегрировать 1С с веб-сервисами и API, а также корректно обрабатывать данные при обмене. Разбираются особенности работы с коллекциями, использование функций восстановления и частые ошибки при работе с JSON и XDTO.

30.01.2025    19991    user2122906    9    

66

Механизмы платформы 1С Файловый обмен (TXT, XML, DBF), FTP Программист 1С:Предприятие 8 Бесплатно (free)

Этот материал познакомит вас с механизмом XDTO (XML Data Transfer Objects) в 1С и научит эффективно использовать его возможности. Мы разберёмся, как работать с XML-схемами, создавать модели данных, манипулировать объектами XDTO, а также сериализовать и десериализовать их в XML. Вы узнаете, как использовать XDTO для интеграции с внешними системами, избегать типичных ошибок и оптимизировать код. К концу вы будете уверенно применять XDTO для решения сложных задач обмена данными и автоматизации процессов.

17.01.2025    34553    user2122906    12    

62

Механизмы платформы 1С WEB-интеграция Программист 1С:Предприятие 8 Бесплатно (free)

В платформе 8.3.27 появилась возможность использовать WebSocket-клиент. Давайте посмотрим, как это все устроено и чем оно нам полезно.

14.01.2025    31064    dsdred    100    

147

Механизмы платформы 1С Программист Стажер 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

Эта небольшая статья - некоторого рода шпаргалка по файловым потокам: как и зачем с ними работать, какие преимущества это дает.

23.06.2024    27455    bayselonarrend    22    

176

Механизмы платформы 1С Программист Стажер 1С:Предприятие 8 1C:Бухгалтерия Бесплатно (free)

Пример использования «Сервисов интеграции» без подключения к Шине и без обменов.

13.03.2024    14918    dsdred    22    

85
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. vladimir_korshun 97 30.03.26 13:28 Сейчас в теме
Очень хочется внедрить RabbitMQ в свою жизнь)
Никак не получается найти подходящую задачу под него.

Главная база и много мини баз. Общение по http-сервисы.
Буфер обмена регистр сведений, что нужно отправить.
Есть связь, отправили, ответ 200. Нет связи - ответ 400. Всё в регламентном задании по расписанию.

Когда мне потребуется RabbitMQ ?
(протоколы поддержки RabbitMQ не обсуждаем, у меня только 1с везде)
2. okniceman 30.03.26 14:09 Сейчас в теме
(1)
RabbitMQ как и многие другие брокеры очередей является в первую очередь способом решения задач асинхронности и маршрутизации и лучше на него смотреть в распределенных системах.

HTTP - синхронный протокол, отправляя запрос вы ожидаете ответ от сервера, это приводит, например, к накладным расходам и необходимости знать адрес получателя.

Представьте, что вы хотите создать номенклатуру в центральной базе и сделать так, чтобы она была в других ваших базах. Их у вас, скажем, 200.
В таком случае вы отправите 200 HTTP запросов (и, если вы захотите отправлять и параллельно, то я напомню что фоновые задания - тяжелая вещь с точки зрения ОС, а http запросы могут и повиснуть в таймауте).
В случае брокера вам достаточно отправить 1 сообщение на обменник, просто заранее настроив его.
Ваши базы обработают сообщения из своих очередей когда будут готовы, даже если какие-то базы были отключены во время отправки.
И отправитель при этом даже не знает что у вас там за базы.

Это всего лишь один из сотни сценариев.
RabbitMQ предоставляет множество различных инструментов для сложных сценариев, сложной маршрутизации, нагрузки, различного рода гарантии и удобства как сам по себе так и на уровне протоколов. Это отдельная большая статья или цикл статей.
Если интерес будет - я напишу их в контексте 1С.
3. vladimir_korshun 97 30.03.26 16:16 Сейчас в теме
(2) Спасибо, стало чуть понятней.
Можно вместо RabbitMQ использовать высокодоступную 1с, как я понял.

http запросы - в них указывается таймаут, чтобы не висли.
"фоновые задания - тяжелая вещь с точки зрения ОС" - таймер много ресурсов есть?

Если интерес будет - я напишу их в контексте 1С.

Да, пишите, вы хорошо объясняете.
4. okniceman 30.03.26 16:53 Сейчас в теме
(3)
Фоновые задания реализованы с помощью потоков операционной системы - это довольно тяжелая с точки зрения ресурсов операционной системы вещь.
У каждого есть стек, у каждого выделяется мегабайт и больше оперативной памяти, переключение контекстов, системные вызовы. И сюда накладываются операции выполняемые платформой.

Теперь представьте что вы запустите по одному заданию на каждый из 200 HTTP-запросов.
Естественно делать так не стоит.
И вы понимая это попробуете запустить, скажем, 10 фоновых заданий, каждое из которых последовательно отправит 20 http-запросов.
Вот здесь - что если вы установили таймаут 15 секунд и один из запросов в фоновом задании повиснет пока соединение не будет разорвано по его окончании? А если одна из систем отвалится с одним из 500-ых или 429-ым кодом который на самом деле можно обработать успешно? Может быть и так что на каждый запрос понадобится выполнить тяжелую операцию, и это тоже потребует ожидания.

В данном случае брокер очередей решает проблему асинхронной передачи сообщений.

У RabbitMQ есть такие понятия как обменник - это правило брокера которое определяет куда должно попасть сообщение, и очередь - это размещенная на диске (или в памяти) структура в которой хранятся отправленные сообщения.
Когда потребитель устанавливает соединение с брокером - брокер проталкивает сообщения из очереди потребителю. Потребитель если не может обработать сообщение (например оно содержит ошибку) может перенаправить его в специальную очередь мертвых сообщений (dead-letter queue) и перейдет к следующему. Затем из этой очереди можно будет перенаправить это сообщение обратно, если ошибка устранена.
Это один из вариантов обработки.

Главное - процессы брокера очень "легковесны", их может быть сотня тысяч и все будет нормально.

Использовать 1С вместо брокера в целом не лучший вариант - как минимум нужно учесть накладные расходы на работу с БД. И HTTP никуда не пропадает, у нас остается синхронность на уровне протокола, необходимость обрабатывать ошибки и повторные попытки соединения.
Для отправки сообщения требуется регистрация/авторизация