Как организовать двухсторонний обмен данными между 1С и внешней системой, передавая только изменения?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При необходимости синхронизации данных между 1С и сторонней системой, одной из ключевых задач становится эффективная передача только измененных данных. Это позволяет минимизировать объем передаваемой информации, снизить нагрузку на обе системы и ускорить процесс обмена. Рассмотрим подробно, как реализовать такую задачу, выбирая оптимальные механизмы регистрации изменений и транспортные протоколы.

Отказ от прямого подключения к базе данных

Прежде всего, крайне важно отказаться от идеи прямого подключения 1С к SQL-базе внешней системы или наоборот. Несмотря на кажущуюся простоту, этот подход считается устаревшим и несёт в себе множество рисков и недостатков:

  1. Зависимость от структуры БД: Любое изменение в структуре таблиц одной из баз данных может мгновенно сломать обмен в другой системе. Это создаёт сильную связность и усложняет развитие обеих систем.
  2. Безопасность: Прямой доступ к базе данных, особенно между разными системами и командами разработчиков, представляет собой серьезную угрозу безопасности данных.
  3. Надежность и производительность: Проблемы с производительностью или доступностью одной базы данных напрямую влияют на работу другой системы. Отсутствие буферизации или очередей может привести к сбоям при временной недоступности.
  4. Сложность поддержки и отладки: Отлаживать проблемы в обмене, основанном на прямом доступе к БД, крайне сложно, так как логика распределена по обеим системам на низком уровне.

Современный и правильный подход заключается в использовании программно-определяемых интерфейсов (API), которые обеспечивают гальваническую развязку между системами.

Механизмы регистрации изменений в 1С

Для передачи только изменений нам необходимо, чтобы 1С надёжно отслеживала эти изменения. Платформа предоставляет несколько способов для этого.

Использование Планов обмена 1С

Планы обмена – это типовой и часто рекомендуемый механизм для регистрации изменений объектов метаданных 1С. Они широко используются в распределенных информационных базах (РИБ) и могут быть адаптированы для обмена с внешними системами.

  1. Назначение: Основное назначение планов обмена – регистрировать факты изменения объектов (справочников, документов, регистров сведений и т.д.) для последующей выгрузки в другие узлы или системы.
  2. Преимущества:
    • Встроенный механизм платформы, не требующий сложной разработки.
    • Автоматическая регистрация изменений при записи объектов, включенных в план обмена.
    • Возможность выбора объектов для регистрации на уровне конфигурации.
  3. Ограничения:
    • Регистрация любого изменения: План обмена регистрирует факт перезаписи объекта, даже если ни один его "значимый" реквизит не изменился (например, документ просто перепровели без изменения данных). Это может привести к передаче избыточной информации.
    • Отсутствие истории: Планы обмена не предназначены для хранения истории изменений. Как только изменение выгружено и подтверждено (или просто выгружено, если нет подтверждения), запись о регистрации может быть удалена.
    • Особенности удаления: План обмена может регистрировать удаление объектов, но это требует дополнительной обработки.

Как работать с зарегистрированными изменениями:

После регистрации изменений, вы можете получить список измененных объектов для определенного узла обмена. Например, для получения всех зарегистрированных изменений для узла с именем ВнешняяСистема:


Функция ПолучитьЗарегистрированныеИзменения(ИмяУзлаОбмена)

    УзелОбмена = ПланыОбмена.НайтиПоНаименованию(ИмяУзлаОбмена);
    Если УзелОбмена = Неопределено Тогда
        Возврат Новый Массив();
    КонецЕсли;

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

    Возврат МассивИзмененныхОбъектов;

КонецФункции

Кастомная регистрация только "значимых" изменений

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

  1. Отключение автоматической регистрации: В плане обмена отключаем автоматическую регистрацию изменений для тех объектов, которые хотим контролировать вручную.
  2. Подписки на события: Создаем подписку на событие ПередЗаписью для нужных объектов метаданных (например, справочников и документов).
  3. Сравнение данных: В обработчике подписки выполняем следующие действия:
    • Получаем текущую (старую) версию объекта из базы данных по ссылке.
    • Сравниваем значимые реквизиты старой и новой (записываемой) версии объекта. Под "значимыми" понимаем те реквизиты, изменение которых должно инициировать обмен с внешней системой.
    • Если обнаружены различия, регистрируем изменение в плане обмена вручную.

Пример сравнения данных:

Для сравнения можно сериализовать объект (или его ключевые реквизиты) в строку JSON/XML или вычислить хэш от значений этих реквизитов. Это позволяет избежать пореквизитного сравнения и упрощает код.


// Пример кода в модуле объекта (или в общем модуле, вызываемом из подписки)
// Допустим, мы хотим сравнивать Контрагента
Процедура ПередЗаписьюКонтрагента(Источник, Отказ, РежимЗаписи, РежимПроведения)
    Если Источник.ОбменДанными.Загрузка Тогда
        Возврат; // Не регистрируем изменения, если это загрузка из другой системы
    КонецЕсли;

    Если Источник.ЭтоНовый() Тогда
        // Для нового объекта всегда регистрируем изменение
        ПланыОбмена.ЗарегистрироватьИзменение(Источники.УзелОбмена, Источник.Ссылка);
        Возврат;
    КонецЕсли;

    // Получаем старую версию объекта
    СтарыйОбъект = Источник.Ссылка.ПолучитьОбъект();

    // Определяем, какие реквизиты критичны для обмена
    КритическиеРеквизиты = Новый Массив();
    КритическиеРеквизиты.Добавить("Наименование");
    КритическиеРеквизиты.Добавить("ИНН");
    КритическиеРеквизиты.Добавить("КПП");
    КритическиеРеквизиты.Добавить("ЮридическийАдрес");

    ИзменилисьКритическиеРеквизиты = Ложь;
    Для Каждого Реквизит Из КритическиеРеквизиты Цикл
        Если СтарыйОбъект[Реквизит] <> Источник[Реквизит] Тогда
            ИзменилисьКритическиеРеквизиты = Истина;
            Прервать;
        КонецЕсли;
    КонецЦикла;

    Если ИзменилисьКритическиеРеквизиты Тогда
        // Регистрируем изменение только если критичные реквизиты изменились
        ПланыОбмена.ЗарегистрироватьИзменение(Источники.УзелОбмена, Источник.Ссылка);
    КонецЕсли;

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

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

Регистрация изменений в регистре сведений

В некоторых случаях, особенно при очень больших объемах данных или нестандартной логике регистрации, бывает удобнее использовать собственный регистр сведений в качестве "очереди" изменений.

  1. Структура регистра: Регистр сведений может хранить ссылку на измененный объект, тип события (создание, изменение, удаление), дату/время изменения, а также, например, хэш передаваемых полей или статус обработки.
  2. Подписки на события: Используем подписки на события ПриЗаписи, ПриУдалении объектов, чтобы записывать информацию об изменениях в этот регистр.
  3. Преимущества:
    • Полный контроль над хранением истории изменений и их статусов.
    • Возможность реализовать сложную логику обработки (например, отслеживание нескольких получателей, повторная отправка).
    • Отсутствие прямого влияния на типовой функционал планов обмена.
  4. Недостатки:
    • Требует полной ручной реализации, включая механизмы очистки регистра.
    • Может быть сложнее в поддержке, чем типовые планы обмена.

Независимо от выбранного механизма регистрации, следующим шагом является выбор транспорта для передачи этих изменений.

Выбор транспортного протокола

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

HTTP-сервисы (REST/JSON)

HTTP-сервисы (часто реализующие REST-интерфейсы с передачей данных в формате JSON) – это современный и очень популярный способ обмена данными с внешними системами. 1С предоставляет мощные средства для их публикации и потребления.

  1. Преимущества:
    • Универсальность и кроссплатформенность: HTTP – это стандартный протокол, понятный практически любой системе и языку программирования.
    • Гибкость: REST-подход позволяет создавать простые и понятные API, адаптированные под конкретные задачи.
    • Легкость разработки в 1С: Платформа 1С имеет встроенные объекты для работы с HTTP-запросами (HTTPСоединение, HTTPЗапрос, HTTPОтвет) и публикации собственных HTTP-сервисов.
    • Безопасность: Поддерживаются стандартные механизмы аутентификации (например, Basic, OAuth) и шифрование (HTTPS).
    • Гальваническая развязка: Отсутствие прямых подключений между базами данных.
  2. HTTP-сервисы vs. Web-сервисы (SOAP/XDTO):
    • HTTP-сервисы (REST): Предпочтительны для обмена с внешними не-1С системами. Используют формат JSON (реже XML), просты и легковесны, хорошо подходят для интеграции с мобильными приложениями, веб-сайтами и микросервисами.
    • Web-сервисы (SOAP): Используют формат XML (XDTO) и являются более формализованными. Они удобны для обмена между двумя 1С-системами или с другими системами, которые строго следуют SOAP-протоколу. Однако для интеграции с современными веб-системами могут быть избыточны и менее гибки.
  3. Реализация двустороннего обмена:
    • 1С как поставщик данных: Вы публикуете HTTP-сервис в 1С, который предоставляет методы для получения измененных данных (например, ПолучитьИзмененияКонтрагентов). Внешняя система периодически "дергает" этот метод, запрашивая новые данные.
    • 1С как потребитель данных: 1С может вызывать HTTP-сервисы внешней системы для получения данных или отправки своих изменений.
    • Двусторонний обмен через один сервис: Один HTTP-сервис может содержать методы как для отдачи данных 1С (например, ПолучитьКонтрагентаПоГУИД), так и для приема данных в 1С (например, ЗаписатьКонтрагента, куда внешняя система передает изменения).

Пример публикации HTTP-сервиса в 1С для получения измененных контрагентов:


// В модуле HTTP-сервиса
// Метод HTTP: GET
// Шаблон URL: /ИзмененияКонтрагентов
Функция ИзмененияКонтрагентовGET(Запрос)

    // Аутентификация (пример)
    Если Не ПроверитьАвторизацию(Запрос) Тогда
        Возврат Новый HTTPСервисОтвет(401);
    КонецЕсли;

    // Получаем узел обмена, для которого зарегистрированы изменения
    УзелОбмена = ПланыОбмена.НайтиПоНаименованию("ВнешняяСистема");
    Если УзелОбмена = Неопределено Тогда
        Возврат Новый HTTPСервисОтвет(500); // Ошибка: узел не найден
    КонецЕсли;

    // Получаем зарегистрированные изменения
    МассивИзменений = Новый Массив();
    ВыборкаИзменений = ПланыОбмена.ВыбратьИзменения(УзелОбмена);

    Пока ВыборкаИзменений.Следующий() Цикл
        СсылкаОбъекта = ВыборкаИзменений.Получить();
        Если ТипЗнч(СсылкаОбъекта) = Тип("СправочникСсылка.Контрагенты") Тогда
            Объект = СсылкаОбъекта.ПолучитьОбъект();
            Если Объект <> Неопределено Тогда
                // Формируем структуру данных для передачи
                СтруктураКонтрагента = Новый Структура();
                СтруктураКонтрагента.Вставить("ГУИД", Строка(Объект.УникальныйИдентификатор));
                СтруктураКонтрагента.Вставить("Наименование", Объект.Наименование);
                СтруктураКонтрагента.Вставить("ИНН", Объект.ИНН);
                СтруктураКонтрагента.Вставить("КПП", Объект.КПП);
                // ... другие реквизиты
                МассивИзменений.Добавить(СтруктураКонтрагента);
            Иначе
                // Если объект удален, можно передать информацию об удалении
                СтруктураУдаления = Новый Структура();
                СтруктураУдаления.Вставить("ГУИД", Строка(СсылкаОбъекта.УникальныйИдентификатор));
                СтруктураУдаления.Вставить("Статус", "Удален");
                МассивИзменений.Добавить(СтруктураУдаления);
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;

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

    // Создаем HTTP ответ
    Ответ = Новый HTTPСервисОтвет(200);
    Ответ.УстановитьТелоИзСтроки(СтрокаJSON, КодировкаТекста.UTF8);
    Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");

    // Удаляем зарегистрированные изменения после успешной выгрузки
    ПланыОбмена.УдалитьРегистрациюИзменений(УзелОбмена);

    Возврат Ответ;

КонецФункции

Функция ПроверитьАвторизацию(Запрос)
    // Реализация проверки авторизации
    // Например, по заголовку Authorization
    Возврат Истина; 
КонецФункции

Брокеры сообщений (RabbitMQ, Apache Kafka)

Для высоконагруженных систем, распределенных архитектур или если требуется асинхронный обмен с гарантированной доставкой и масштабируемостью, целесообразно использовать брокеры сообщений, такие как RabbitMQ или Apache Kafka.

  1. Когда использовать:
    • Высокие объемы данных и сообщений.
    • Необходимость асинхронной обработки, чтобы 1С не ждала ответа от внешней системы.
    • Множество систем-потребителей, которым нужны одни и те же данные.
    • Требования к отказоустойчивости и масштабируемости.
    • Корпоративная архитектура уже включает брокер сообщений.
  2. Принцип работы:
    • Издатель (Publisher): 1С отправляет (публикует) сообщения об изменениях в брокер сообщений.
    • Подписчик (Subscriber/Consumer): Внешняя система (или несколько систем) "слушает" брокер и забирает сообщения для обработки.
    • Очереди/Топики: Сообщения хранятся в очередях (RabbitMQ) или топиках (Kafka), пока не будут обработаны.
  3. Преимущества:
    • Асинхронность: 1С "выплевывает" сообщение и не ждет его обработки, продолжая свою работу.
    • Надежность и гарантия доставки: Сообщения не теряются, даже если потребитель временно недоступен.
    • Масштабируемость: Брокеры легко масштабируются для обработки больших объемов.
    • Развязка систем: Системы слабо связаны, не знают друг о друге напрямую.
  4. Интеграция 1С с Kafka:
    • Kafka REST Proxy: Наиболее универсальный способ. Это официальный или самописный микросервис, который предоставляет стандартный HTTP (REST) API для взаимодействия с Kafka. 1С общается с этим прокси через HTTPСоединение и HTTPЗапрос, отправляя/получая сообщения. Это избавляет от необходимости использовать внешние компоненты.
    • Внешние компоненты: Существуют внешние компоненты для 1С (например, от "Серебряной Пули" для RabbitMQ), которые позволяют напрямую работать с брокерами. Однако их использование может быть связано с лицензированием, совместимостью и сложностью поддержки.
    • Кастомный микросервис: Вы можете разработать свой небольшой микросервис на любом удобном языке (Java, Python, Go), который будет выступать посредником между 1С и Kafka, предоставляя 1С простой HTTP-интерфейс.

Пример структуры сообщения для брокера (JSON):


{
  "messageId": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d", // Уникальный GUID сообщения для идемпотентности
  "sourceSystem": "1C_ERP",                        // Система-источник
  "timestamp": "2023-10-27T10:30:00Z",             // Время отправки
  "eventType": "Контрагент.Изменен",              // Тип события
  "payload": {                                     // Полезные данные
    "id": "e674a2b9-7b3e-4d5c-9c0a-0f8e1a2b3c4d",   // GUID контрагента
    "inn": "1234567890",
    "kpp": "098765432",
    "name": "ООО 'Пример Измененный'",
    "address": "г. Москва, ул. Примерная, д.1",
    "isActive": Истина
  }
}

Этот пример демонстрирует "конверт" сообщения с метаданными (messageId, sourceSystem, eventType) и payload с фактическими данными. Это позволяет потребителям эффективно маршрутизировать и обрабатывать сообщения.

Файловый обмен

В простейших случаях, когда нет высоких требований к оперативности и надежности, можно использовать файловый обмен через общую сетевую папку или FTP. 1С выгружает изменения в файлы (JSON, XML), а внешняя система их забирает. И наоборот. Это наименее надёжный, но самый простой в реализации вариант.

  1. Принцип: 1С формирует файл с измененными данными и помещает его в "исходящую" папку. Внешняя система сканирует эту папку, забирает файлы, обрабатывает и, возможно, перемещает их в "архивную" или "обработанную" папку. Аналогично для входящих данных.
  2. Недостатки: Отсутствие гарантии доставки, нет механизма очередей, ручная обработка ошибок, возможны конфликты при одновременном доступе.

Архитектурные паттерны для надежного обмена

Для построения по-настоящему надежной и масштабируемой системы обмена, особенно с использованием брокеров сообщений, необходимо учитывать следующие архитектурные паттерны:

  1. Разделение ответственности (Separation of Concerns):
    • Служба регистрации изменений: Отвечает только за фиксацию факта изменения данных в 1С (планы обмена, регистр сведений, подписки).
    • Служба транспорта: Отвечает за передачу сообщений в/из брокера или через HTTP-сервисы.
    • Служба логирования: Отвечает за запись всех событий обмена, отправленных/полученных данных для последующего анализа и отладки.
  2. Идемпотентность (Idempotency):

    Принимающая сторона должна быть спроектирована так, чтобы повторное получение одного и того же сообщения не приводило к дублированию данных или некорректным операциям. Это особенно важно для асинхронных систем, где сообщения могут быть отправлены повторно из-за сетевых сбоев. Достигается путем присвоения каждому сообщению уникального идентификатора (messageId) и сохранения обработанных идентификаторов на принимающей стороне.

  3. Пакетная отправка данных (Batching):

    Вместо отправки сообщения на каждое отдельное изменение, гораздо эффективнее накапливать изменения в течение определенного периода (например, 1 минута) и отправлять их пачками в одном сообщении или HTTP-запросе. Это значительно снижает сетевые издержки и нагрузку на сервис.

  4. Очередь "мертвых" сообщений (Dead-Letter Queue - DLQ):

    Если внешняя система не может обработать сообщение из очереди (например, из-за неверного формата или бизнес-логики), оно должно быть перемещено в специальную DLQ. Это предотвращает блокировку основной очереди и позволяет разработчикам позже проанализировать и исправить ошибочные сообщения.

  5. Change Data Capture (CDC):

    Для продвинутых архитектур можно использовать технологии CDC на уровне базы данных (например, Debezium для PostgreSQL или MS SQL). Это специализированное ПО "слушает" журнал транзакций БД и публикует все изменения напрямую в брокер сообщений (Kafka), полностью снимая эту нагрузку с 1С. Это идеальное решение для нулевого влияния на производительность 1С, но требует сложной настройки и инфраструктуры.

Организация двустороннего обмена

Для двухстороннего обмена данными существует несколько подходов к расположению сервисов:

  1. Один сервис на стороне 1С:

    1С публикует HTTP-сервис. Внешняя система вызывает методы этого сервиса как для получения данных из 1С (GET-запросы), так и для отправки данных в 1С (POST-запросы). Этот подход часто используется, когда 1С является центральной системой учета.

  2. Один сервис на стороне внешней системы:

    Внешняя система предоставляет API. 1С является активным инициатором обмена, вызывает методы внешней системы как для отправки своих изменений, так и для получения данных. Это снижает нагрузку на 1С, так как она не должна быть постоянно доступна для входящих запросов.

  3. Оба публикуют сервисы (сложнее):

    1С публикует свои сервисы, внешняя система публикует свои. Это может усложнить общую архитектуру и поддержку, так как появляется больше точек отказа и координации.

Выбор, кто будет публиковать сервис, а кто потреблять, часто зависит от того, какая система является "главной" (master-системой) для конкретного типа данных, и от общих требований к безопасности и доступности.

Заключение

Организация обмена данными с передачей только изменений между 1С и внешней системой — это комплексная задача, требующая продуманного подхода. Мы выяснили, что планы обмена в связке с HTTP-сервисами (REST/JSON) являются хорошим стандартом де-факто для большинства случаев. При высоких нагрузках, масштабируемости и асинхронности, брокеры сообщений, такие как Apache Kafka, становятся предпочтительным выбором, особенно если они уже используются в корпоративной инфраструктуре.

Критически важно реализовать кастомный механизм регистрации "значимых" изменений (через подписки на события с сравнением данных или собственный регистр сведений), чтобы избежать избыточной передачи. Не менее важны архитектурные принципы, такие как идемпотентность, пакетная отправка и разделение ответственности, которые обеспечат надежность и стабильность вашей системы интеграции.

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

← На главную