Большинство подобных статей в сообществе 1С почему-то начинаются с тезисов о том, что "интеграции в 1С – это боль и страдание". Дальше обычно идет длинная статья о том, как "делать интеграции без боли".
Мы в компании RDV с этим подходом категорически не согласны. Интеграции в 1С – это не боль, интеграции в 1С – это нормально. Иногда даже интересно.
И как ни крути, любой разработчик грейдом выше джуна так или иначе с ними сталкивается. А уж разработчика, который дорос до ТА, чем-то удивить в части интеграций в принципе сложно – все всё уже видели.
В каждой команде обычно есть свои наработки, подходы и проверенные временем куски кода. Мы тоже были такой командой. У нас были свои модули, подсистемы, которые через "сравнение-объединение" перекочевывали из проекта в проект, и на каждом проекте "допиливались" под конкретные требования.
Правда, аналитики постоянно жаловались:
- то ошибки забыли залогировать
- то логи вообще потерялись
- то очистку логов забыли
- то на вопросы "а где посмотреть что не выгрузилось", "а как зарегистрировать к обмену" почему-то на каждом проекте каждый раз новые ответы...
В общем, нам просто в какой-то момент это все надоело, и мы решили разработать готовое решение для настройки и разработки интеграций. Разработали, обкатали на нескольких проектах и поняли, что не стыдно им поделиться.
Так появился RDV-MI, он же Модуль Интеграции, он же MI, он же "MIшка". Продукт, который лежит на github и которым можно пользоваться.
Мы не позиционируем MI как "решение проблемы интеграций". Потому что такой проблемы в мире 1С не существует. Все и без нас знают и умеют работать с интеграциями. Но при этом MI может оказаться полезным тем, кто разделяет наши идеи и архитектурные принципы. Поэтому в данной статье мы не будем рассказывать почему MI "лучше конкурентов" и не будем "делиться бесценным опытом". Мы просто расскажем, какие подходы к архитектуре интеграций считаем правильными, почему придерживаемся именно их и как эти принципы привели к тому, что MI стал таким, какой он есть.
Атомарность и последовательность
Один объект – одно сообщение. Почему мы против пакетов? Если объединять объекты в пакеты, неизбежно возникнет классическая ситуация: выгружаем 1000 документов, один падает - откатывается вся транзакция загрузки. Особенно приятно это все наблюдать в высоконагруженной системе, где накопившиеся недоставленные пакеты накопятся в очередь, которая сможет рассосаться примерно никогда. Кроме того, все, кто сталкивался с поиском и отладкой ошибок в типовых пакетных обменах 1С знают насколько это "удобно". Мы сталкивались – нам хватило.
Технический бонус: мы любим использовать брокеры сообщений, а брокеру гораздо комфортней пропускать 1000 маленьких сообщений, чем одно огромное.
Последствия атомарности. Раз мы не объединяем объекты выгрузки в пакеты, значит нам необходимо по умолчанию соблюдать последовательность. В каком порядке объекты создавались (редактировались) в источнике – в таком они должны появляться в приемнике. Почему? Потому что мы не хотим, чтобы в приемник прилетел сначала договор, а потом контрагент. Да, мы можем записать "битую" ссылку в поле "Владелец" у договора и ждать, когда "доедет" контрагент. При этом, если для контрагентов реализован поиск по ИНН-КПП и найдётся контрагент с другим GUID, то ссылка так и останется битой навсегда.
Как это реализовано в MI. В MI регистрация изменений идет не в план обмена, а в специальный регистр сведений. Каждая его запись – это один объект, с привязкой к точке обмена и с таймстемпом до миллисекунд для сортировки. Таким образом, одна запись = одно атомарное сообщение = один элемент очереди на обработку. Это дает прозрачность, контроль и предсказуемость на всех этапах.
Понятный и гибкий формат. Стандартный JSON с возможностью адаптации
Мы используем формат JSON. Почему, думаем, объяснять в XXI веке никому не нужно. Как выглядит текст сообщения (упрощенный пример):
{
"data": [
{
"_ИмяОбъекта": "Справочник.Контрагенты",
"_ТипЗначения": "Справочник.Контрагенты",
"_GUID": "689c1ccc-d02c-11f0-9a80-ac1f6bd14f0a",
"Наименование": "_Тестовый контрагент",
"ИНН": "7725396754",
"ЮрФизЛицо": {
"_ТипЗначения": "Перечисление.ЮрФизЛицо",
"_Значение": "ЮрЛицоНеРезидент"
}
// ...
}
],
"meta": {
"id": "a1582635-fcbc-4648-a47d-dac6d3c5",
"baseid": "erp1",
"timestamp": "2025-12-03T09:42:40",
"objecttype": "Контрагенты"
}
}
Сообщение делится на два блока:
-
data - сами данные объекта;
-
meta - служебная информация.
Внутри секции data присутствуют служебные поля, такие как "_ИмяОбъекта" или "_ТипЗначения". Они нужны, чтобы MI на стороне приемника мог и самостоятельно идентифицировать, и подобрать нужные значения на этапе загрузки, без дополнительных действий со стороны разработчика. Начинаются с символа "_", чтобы явно их отделить от значений реквизитов. Да, это может выглядеть эстетически непривлекательно и можно было бы их объединить во вложенные объекты JSON, или снабдить префиксом, но не хотелось на текущем этапе усложнять формат сообщения и себе жизнь. Поэтому пока так, может быть когда-нибудь переделаем.
Поля ниже – значения выгружаемых реквизитов. Для примитивных типов вроде бы все очевидно. Ссылочные типы содержат вложенные объекты с обязательным полем "_ТипЗначения".
Секция meta – служебные данные сообщения. Напрямую на логику работы MI не влияют вообще никак, но полезны если в архитектуру включена система мониторинга. Спойлер – у нас такая есть, она готовая, тоже в открытом доступе, о ней чуть ниже.
Больше никаких хитростей нет, всего этого достаточно, чтобы база-приемник с MI на другом конце понимала, что к ней прилетело и что с этим делать.
Как быть, если требуется реализовать другой формат? Например, мы хотим обмениваться данными с сайтом, у которого свои требования к JSON, без вложенных объектов, без типов, плоская структура, ключи полей латиницей.
Для выполнения этой задачи, нужно в источнике в специальной переопределяемой процедуре написать код, приблизительно такого вида:

На выходе в секции data получим плоскую структуру, секцию meta по нашему стандарту. Если хотим еще упростить и совсем избавиться от секций data и meta – можно: решается внесением еще нескольких строчек кода. Потеряется возможность мониторинга, но кто мы такие, чтобы запрещать.
Что может работать само - должно работать само. Минимум прикладного кода
Мы хотим, чтобы вход в разработку интеграций был максимально простым. Все, что может работать само "из коробки" должно работать "само из коробки". Если мы понимаем, что в 90% случаев при выгрузке ссылочного реквизита нам в приемнике понадобится его GUID, это означает, что разработчик прикладной интеграции об этом думать вообще не должен. Разработчик должен указать, какой реквизит он хочет выгрузить, все остальное MI понимает и сам. Дополнительные действия требуются только в оставшиеся 10% случаев.
Чтобы запустилась выгрузка. необходимо в переопределяемом модуле написать код, примерно такого вида

Нет, это не дежа вю. Это, действительно, код похожий на код, который используется в типовых конфигурациях для написания обменов в формате EnterpriseData. Мы его не украли, мы им вдохновлялись. Нам понравился подход, при котором все правила конвертации существуют в единой абстрактной коллекции значений. Ну и привыкать к подобному коду разработчику, знакомому с EnterpriseData, будет проще.
Если нужно реализовать более сложную логику, предусмотрен набор переопределяемых процедур, вызываемых в ключевых шагах процесса выгрузки и загрузки и дающих возможность внести любые изменения в загружаемые и выгружаемые данные на любом из этапов.

MI содержит демонстрационные модули, в которых написан демонстрационный код выгрузки и загрузки. Чтобы посмотреть пример и почитать документацию, разработчику не нужно уходить из конфигуратора.

Low-code?
Low-code в мире 1С - это миф и маркетинг, который к реальности отношения не имеет. Первый “low-code инструмент” для интеграций придумала ещё сама 1С во времена 7.7 – это “Конвертация данных 2”. Но почему-то интерактивная настройка сопоставления реквизитов, столкнувшись с реальными типовыми конфигурациями и реальными задачами, помогает мало. Итог всегда один и тот же: всё равно приходится писать сотни строк кода. Только зачем-то в режиме предприятия и без отладки. Не верите – откройте любые типовые правила обмена между типовыми базами.
Бывают ли задачи, где действительно можно было бы обойтись low-code? Да, бывают. Крайне редко. Обычно это какой-нибудь MDM с централизованной НСИ. Но мы работаем с 1C:ERP и 1C:ERP УХ. Покажите нам low-code инструмент, который позволит без единой строчки кода загружать договоры, версии договоров, контрагентов и партнёров, учёт которых ведётся раздельно, а также документ “Заказ клиента” с учётом типового механизма обеспечения потребностей из 1C:УПП в 1C:ERP УХ – мы искренне порадуемся этому инструменту вместе с вами.
Low-code инструменты, работа с которыми всё равно заканчивается задачей "разработчик, помоги, у меня тут не работает", – как будто теряют свой изначальный смысл.
И ещё момент. Код конвертации, который находится в конфигурации (или расширении – разницы нет), поставляется и тестируется централизованно, живёт в одном месте, не теряется, нормально версионируется гитом и не превращается в горсть внешних файлов.
"Почему обмен встал? Потому что мы десять текстовых файлов перенесли из теста в прод, а одну внешнюю обработку забыли". Думаю, знакомая всем история. У нас такого уже давно нет – и мы хотим, чтобы так было и у вас.
Транспорт обмена
В 99% случаев нам хватает двух транспортов:
- RabbitMQ
- HTTP-сервис
Какой использовать? Логика простая. Если архитектура интеграции предполагает:
- всего две базы (неважно, односторонний или двусторонний обмен)
- отсутствие перспектив расширения и масштабирования (часто это просто временный обмен на период миграции)
то можно использовать HTTP-сервис. Во всех остальных случаях мы используем RabbitMQ.
Почему брокер в приоритете.
Потому что брокер убирает необходимость маршрутизации на стороне 1С. База-источник ничего не знает про приемники – и это прекрасно. У источника ровно одна задача: выгрузить сообщение в брокер. Получить обратно статус обработки – приятно, но это именно приятный бонус, а не квитирование и не команда “переотправь”. Источник свою работу сделал в момент отправки.
Добавление новой базы-приёмника не требует менять архитектуру. Появился новый потребитель справочника “Контрагенты”?
-
создаём новую очередь в брокере,
-
пишем код загрузки в приёмнике,
-
источник об этом не знает и знать не должен.
Это, кстати, ещё один аргумент в пользу того, почему мы не объединяем разные объекты в одно сообщение. В брокере мелкими атомарными сообщениями гораздо проще управлять, маршрутизировать и подключать к ним новых потребителей.
На текущий момент времени MI поддерживает оба этих транспорта. Kafka – в ближайших планах. Файловый обмен, обмен через почту, через FTP – нам такое неинтересно, но если вам нужно, велкам. Контрибьют приветствуется, добавить новый транспорт в MI несложно.
Почему не ESB
Мы не хотим подгонять данные под чей-то формат. В модели с шиной приходится сначала приводить выгрузку к формату шины, потом формат шины приводить к формату приемника. Мы этого делать не хотим. Более того, мы даже не хотим подгонять сообщения под приемник на стороне источника. Источник должен выгружать объект как есть, в максимально естественном виде. Все остальное – забота приемника. Да, бывают специфические случаи, когда в сообщение нужно добавить связанные данные, но это именно исключение. В 90% случаев мы просто сериализуем объект в JSON. Источник ничего не знает о приемниках, и мы хотим, чтобы так оно и оставалось
Мы не хотим писать и хранить код вне конфигуратора. В шинах это обычная практика и мы в нее не верим. Почему – уже рассказали выше в разделе low-code.
Нужен новый приемник – не трогай источник. Добавляем новую очередь в брокере, пишем обработчик загрузки в приемнике и все. Источник не трогаем. Шину не трогаем. Архитектуру не меняем. Это быстро, просто и удобно.
Шина – это всегда отдельная техподдержка. Стандартная история: сообщение потерялось, шина повела себя странно, внутренняя логика работы шины от нас закрыта. "Обращайтесь в саппорт шины, специалист вернется с курортов Краснодарского края – посмотрит." Нам лишний "черный ящик" в цепочке интеграции не нужен. Зачем плодить узлы, которые требуют отдельного мониторинга, обновлений, логирования и человеческих ресурсов?
Нет, мы никого не агитируем "не использовать шины". Если кому-то удобно – пожалуйста. Просто нам комфортнее, предсказуемее и дешевле работать без них.
Высокая скорость обмена
Мы уже описали наш подход: один объект – одно сообщение, последовательная выгрузка.
Но что делать, если обмен нужно ускорить? Или данных настолько много, что очередь превращается в "будет готово через два часа"? Или проект только запускается, и нужно прогрузить сотни тысяч элементов НСИ, а ждать никто не хочет?
Если посмотреть на цепочку обработки:
собрать данные → сформировать сообщение → доставить → распарсить → записать объект в приемник,
то самое узкое место всегда одно и то же – запись объекта в приемнике.
Да, иногда "сбор данных" может тормозить, но это происходит только если разработчик сам себе "выстрелил в ногу". В 99% случаев данные вытаскиваются одним нормальным запросом, даже если нужно подтянуть какие-то дополнительные реквизиты.
Поэтому ускорять нужно именно этап записи в приемник.
Логичный путь – распараллелить то, что можно распараллелить.
Но любое распараллеливание в 1С - это история про осознанность: блокировки, конкурирующие записи, "битые ссылки", несогласованность данных и так далее. Поэтому MI не пытается автоматически "параллелить все подряд". Мы даем инструменты, а решения принимает разработчик.
В MI встроен механизм “отложенной обработки” – мы обычно называем его просто механизм очередей. Любое событие можно выполнить отложено, и загрузка входящих сообщений тоже работает через него.
Внутри этой подсистемы есть:
-
возможность параллелить обработку в рамках одного типа очереди;
-
возможность заводить разные типы очередей, каждая из которых выполняется параллельно с другими.
Поэтому если хочется ускорить загрузку, нас не волнует строгая последовательность, и мы не боимся блокировок, достаточно включить многопоточную обработку для очереди “Обработка входящих сообщений”.
Если же нужна более тонкая логика - пожалуйста: определяем, какие типы сообщений можно обрабатывать параллельно, и регистрируем их в разные типы очередей. Максимальная гибкость и полный контроль со стороны разработчика.

Запрос "дозагрузки" от приемника - антипаттерн
Регулярно сталкиваемся с предложением “решения проблемы битых ссылок” примерно в такой формулировке:
“Если в приёмнике ссылка не найдена, мы отправляем служебное сообщение в источник, он по GUID выгружает недостающий объект, и все работает”.
Подход рабочий – но только пока интеграция состоит из полутора объектов и одного направления обмена.
Как только в обмен вовлечено 30–40 сущностей, у которых есть взаимные ссылки, плюс многосторонний обмен – вся эта схема превращается в прямой путь к зацикливанию запросов, лавине повторных дозагрузок и вполне реальному шансу положить обмен целиком.
Поддерживать такую архитектуру сложно.
Расследовать инциденты – еще сложнее.
Риски – абсолютно ненужные.
Мы никого не критикуем – каждый делает так, как ему удобно.
Но мы с этим подходом сталкивались достаточно раз, чтобы больше никогда так не делать.
И в MI мы сознательно не закладываем такой механизм: он нестабилен по природе и плохо масштабируется.
Контроль целостности данных
Данная задача возникает всегда. Не было ни одного проекта, на котором после настройки интеграции не пришлось бы явно убеждать себя и заказчика в том, что интеграция выполнена корректно и ничего не потерялось. Мы считаем, что данная задача должна решаться "из коробки" и MI это умеет.
Общий подход к контролю работает следующим образом
- Для каждого объекта на стороне источника и приемника формируется массив реквизитов, которые участвуют в обмене (с заданными правила конвертации)
- Формируется хеш данного массива
- Хеш обменивается между источником и приемником
- На стороне источника и приемника есть отчет, который сравнивает хеши
На выходе мы имеем информацию
- Какие объекты отличаются в источнике и приемнике
- Какие объекты в какую базу выгружены
- Какие объекты не выгружены никуда (или никуда не доехали)

Да, мы бы хотели иметь более подробную информацию – сравнивать не только хеши, но и иметь возможность явно увидеть, какие реквизиты разошлись. Данная задача запланирована и находится в разработке. Ждите обновлений.
Да, кстати, для запуска механизма контроля целостности в "простой" версии достаточно просто взвести флажок в соответствующей константе, все остальное заработает "само". Хеш будет формироваться по значениям всех реквизитов, которые участвуют в правилах конвертации. Для "сложных" правил формирования хешей есть переопределяемые процедуры. Таким образом, наш принцип, который мы описывали ранее – все, что может работать "само" должно работать "само", – полностью поддерживается.
Мониторинг
Мы не любим узнавать о наличии проблем от пользователей. Мы хотим проблемы предотвращать. Для этого мы всегда используем инструмент, который дает ответы на вопросы.
- Все ли базы "живы"?
- Что происходит со скоростью обмена?
- Есть ли недоставленные сообщения?
- Нет ли переполнения очередей?
и так далее.
Мы разработали специальный продукт MI-monitor, который также выложен в открытый доступ. Он представляет собой Clickhouse + Grafana с преднастроенными таблицами и дашбордами. И все это заточено под формат сообщений MI, а также под чтение данных из RabbitMQ или HTTP. Вот один из дашбордов графаны, который показывает скорость доставки. Остальные можно посмотреть по ссылке ниже.

Как поучаствовать
Ссылки
RDV-MI: https://github.com/rdv-team/mi
RDV-MI Monitor: https://github.com/rdv-team/mi-monitor/
Пообщаться с нами в тг можно по ссылке со страницы проекта в github
Видео "Быстрый запуск"
У нас есть ролик, где показано как подключить MI, как настроить транспорт, как создать первый обмен и загрузить объект. Повторить все самостоятельно можно, примерно, за час.
Документация
Документация нормальная. Не “три абзаца и картинка”, а человеческая. Мы знаем, что для мира 1С такое редкость, но мы справились.
Итог
RDV-MI – это не попытка "внести свет" на рынок интеграций 1С. Это просто аккуратно собранный набор решений, которые мы десятки раз делали вручную.
Теперь они живут в одном модуле.
Если вам близок такой подход – используйте.
Если хотите посмотреть внимательно – заглядывайте в GitHub.
Если хотите поругать – пишите комментарий, комментарии улучшают ER и CTR статьи, а мы только рады.
Вступайте в нашу телеграмм-группу Инфостарт
