При необходимости синхронизации данных между 1С и сторонней системой, одной из ключевых задач становится эффективная передача только измененных данных. Это позволяет минимизировать объем передаваемой информации, снизить нагрузку на обе системы и ускорить процесс обмена. Рассмотрим подробно, как реализовать такую задачу, выбирая оптимальные механизмы регистрации изменений и транспортные протоколы.
Прежде всего, крайне важно отказаться от идеи прямого подключения 1С к SQL-базе внешней системы или наоборот. Несмотря на кажущуюся простоту, этот подход считается устаревшим и несёт в себе множество рисков и недостатков:
Современный и правильный подход заключается в использовании программно-определяемых интерфейсов (API), которые обеспечивают гальваническую развязку между системами.
Для передачи только изменений нам необходимо, чтобы 1С надёжно отслеживала эти изменения. Платформа предоставляет несколько способов для этого.
Планы обмена – это типовой и часто рекомендуемый механизм для регистрации изменений объектов метаданных 1С. Они широко используются в распределенных информационных базах (РИБ) и могут быть адаптированы для обмена с внешними системами.
Как работать с зарегистрированными изменениями:
После регистрации изменений, вы можете получить список измененных объектов для определенного узла обмена. Например, для получения всех зарегистрированных изменений для узла с именем ВнешняяСистема:
Функция ПолучитьЗарегистрированныеИзменения(ИмяУзлаОбмена)
УзелОбмена = ПланыОбмена.НайтиПоНаименованию(ИмяУзлаОбмена);
Если УзелОбмена = Неопределено Тогда
Возврат Новый Массив();
КонецЕсли;
ВыборкаИзменений = ПланыОбмена.ВыбратьИзменения(УзелОбмена);
МассивИзмененныхОбъектов = Новый Массив();
Пока ВыборкаИзменений.Следующий() Цикл
Попытка
ОбъектСсылка = ВыборкаИзменений.Получить();
МассивИзмененныхОбъектов.Добавить(ОбъектСсылка);
Исключение
// Возможно, объект был удален после регистрации
// Или это ссылка на несуществующий объект
КонецПопытки;
КонецЦикла;
Возврат МассивИзмененныхОбъектов;
КонецФункции
Чтобы избежать избыточной передачи данных при использовании планов обмена (например, при простом перепроведении документа), можно реализовать собственный механизм, который будет регистрировать изменения только тогда, когда это действительно необходимо.
ПередЗаписью для нужных объектов метаданных (например, справочников и документов).Пример сравнения данных:
Для сравнения можно сериализовать объект (или его ключевые реквизиты) в строку JSON/XML или вычислить хэш от значений этих реквизитов. Это позволяет избежать пореквизитного сравнения и упрощает код.
// Пример кода в модуле объекта (или в общем модуле, вызываемом из подписки)
// Допустим, мы хотим сравнивать Контрагента
Процедура ПередЗаписьюКонтрагента(Источник, Отказ, РежимЗаписи, РежимПроведения)
Если Источник.ОбменДанными.Загрузка Тогда
Возврат; // Не регистрируем изменения, если это загрузка из другой системы
КонецЕсли;
Если Источник.ЭтоНовый() Тогда
// Для нового объекта всегда регистрируем изменение
ПланыОбмена.ЗарегистрироватьИзменение(Источники.УзелОбмена, Источник.Ссылка);
Возврат;
КонецЕсли;
// Получаем старую версию объекта
СтарыйОбъект = Источник.Ссылка.ПолучитьОбъект();
// Определяем, какие реквизиты критичны для обмена
КритическиеРеквизиты = Новый Массив();
КритическиеРеквизиты.Добавить("Наименование");
КритическиеРеквизиты.Добавить("ИНН");
КритическиеРеквизиты.Добавить("КПП");
КритическиеРеквизиты.Добавить("ЮридическийАдрес");
ИзменилисьКритическиеРеквизиты = Ложь;
Для Каждого Реквизит Из КритическиеРеквизиты Цикл
Если СтарыйОбъект[Реквизит] <> Источник[Реквизит] Тогда
ИзменилисьКритическиеРеквизиты = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Если ИзменилисьКритическиеРеквизиты Тогда
// Регистрируем изменение только если критичные реквизиты изменились
ПланыОбмена.ЗарегистрироватьИзменение(Источники.УзелОбмена, Источник.Ссылка);
КонецЕсли;
КонецПроцедуры
Такой подход позволяет точно контролировать, что именно считается изменением, требующим передачи во внешнюю систему. При этом стоит учитывать, что такие сравнения могут незначительно влиять на производительность при очень высоких нагрузках, но в большинстве случаев это влияние минимально.
В некоторых случаях, особенно при очень больших объемах данных или нестандартной логике регистрации, бывает удобнее использовать собственный регистр сведений в качестве "очереди" изменений.
ПриЗаписи, ПриУдалении объектов, чтобы записывать информацию об изменениях в этот регистр.Независимо от выбранного механизма регистрации, следующим шагом является выбор транспорта для передачи этих изменений.
Транспорт определяет, как данные будут фактически передаваться между системами. Существует несколько популярных вариантов, каждый со своими особенностями.
HTTP-сервисы (часто реализующие REST-интерфейсы с передачей данных в формате JSON) – это современный и очень популярный способ обмена данными с внешними системами. 1С предоставляет мощные средства для их публикации и потребления.
HTTPСоединение, HTTPЗапрос, HTTPОтвет) и публикации собственных HTTP-сервисов.ПолучитьИзмененияКонтрагентов). Внешняя система периодически "дергает" этот метод, запрашивая новые данные.ПолучитьКонтрагентаПоГУИД), так и для приема данных в 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.
HTTPСоединение и 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), а внешняя система их забирает. И наоборот. Это наименее надёжный, но самый простой в реализации вариант.
Для построения по-настоящему надежной и масштабируемой системы обмена, особенно с использованием брокеров сообщений, необходимо учитывать следующие архитектурные паттерны:
Принимающая сторона должна быть спроектирована так, чтобы повторное получение одного и того же сообщения не приводило к дублированию данных или некорректным операциям. Это особенно важно для асинхронных систем, где сообщения могут быть отправлены повторно из-за сетевых сбоев. Достигается путем присвоения каждому сообщению уникального идентификатора (messageId) и сохранения обработанных идентификаторов на принимающей стороне.
Вместо отправки сообщения на каждое отдельное изменение, гораздо эффективнее накапливать изменения в течение определенного периода (например, 1 минута) и отправлять их пачками в одном сообщении или HTTP-запросе. Это значительно снижает сетевые издержки и нагрузку на сервис.
Если внешняя система не может обработать сообщение из очереди (например, из-за неверного формата или бизнес-логики), оно должно быть перемещено в специальную DLQ. Это предотвращает блокировку основной очереди и позволяет разработчикам позже проанализировать и исправить ошибочные сообщения.
Для продвинутых архитектур можно использовать технологии CDC на уровне базы данных (например, Debezium для PostgreSQL или MS SQL). Это специализированное ПО "слушает" журнал транзакций БД и публикует все изменения напрямую в брокер сообщений (Kafka), полностью снимая эту нагрузку с 1С. Это идеальное решение для нулевого влияния на производительность 1С, но требует сложной настройки и инфраструктуры.
Для двухстороннего обмена данными существует несколько подходов к расположению сервисов:
1С публикует HTTP-сервис. Внешняя система вызывает методы этого сервиса как для получения данных из 1С (GET-запросы), так и для отправки данных в 1С (POST-запросы). Этот подход часто используется, когда 1С является центральной системой учета.
Внешняя система предоставляет API. 1С является активным инициатором обмена, вызывает методы внешней системы как для отправки своих изменений, так и для получения данных. Это снижает нагрузку на 1С, так как она не должна быть постоянно доступна для входящих запросов.
1С публикует свои сервисы, внешняя система публикует свои. Это может усложнить общую архитектуру и поддержку, так как появляется больше точек отказа и координации.
Выбор, кто будет публиковать сервис, а кто потреблять, часто зависит от того, какая система является "главной" (master-системой) для конкретного типа данных, и от общих требований к безопасности и доступности.
Организация обмена данными с передачей только изменений между 1С и внешней системой — это комплексная задача, требующая продуманного подхода. Мы выяснили, что планы обмена в связке с HTTP-сервисами (REST/JSON) являются хорошим стандартом де-факто для большинства случаев. При высоких нагрузках, масштабируемости и асинхронности, брокеры сообщений, такие как Apache Kafka, становятся предпочтительным выбором, особенно если они уже используются в корпоративной инфраструктуре.
Критически важно реализовать кастомный механизм регистрации "значимых" изменений (через подписки на события с сравнением данных или собственный регистр сведений), чтобы избежать избыточной передачи. Не менее важны архитектурные принципы, такие как идемпотентность, пакетная отправка и разделение ответственности, которые обеспечат надежность и стабильность вашей системы интеграции.
Начните с четкого определения, что именно считается "изменением" для каждого объекта, и какие требования к оперативности и объему обмена. Это поможет выбрать наиболее подходящие механизмы регистрации и транспортного протокола для вашей конкретной задачи.