
Большинство подобных статей в сообществе 1С почему‑то начинаются с тезисов о том, что «интеграции в 1С — это боль и страдание». Дальше обычно идет длинная статья о том, как «делать интеграции без боли».
Мы с этим подходом категорически не согласны. Интеграции в 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/
Чат продукта в тг: https://t.me/rdv_mi
Видео "Быстрый запуск"
У нас есть ролик, где показано как подключить MI, как настроить транспорт, как создать первый обмен и загрузить объект. Повторить всё самому можно, примерно, за час.
Документация
Документация нормальная. Не “три абзаца и картинка”, а человеческая. Мы знаем, что для мира 1С такое редкость, но мы справились.
Итог
RDV-MI – это не попытка "внести свет" на рынок интеграций 1С. Это просто аккуратно собранный набор решений, которые мы десятки раз делали вручную.
Теперь они живут в одном модуле.
Если вам близок такой подход – используйте.
Если хотите посмотреть внимательно – заглядывайте в GitHub.
Если хотите поругать – пишите комментарий, комментарии улучшают ER и CTR статьи, а мы только рады.