При организации распределенных информационных баз (РИБ) или обмена данными между центральным офисом и удаленными филиалами разработчики часто сталкиваются с проблемой "тяжелых" пакетов обмена. Если в периферийных узлах (например, на отдаленных складах или мобильных точках) пользователи активно прикрепляют к документам медиафайлы — фотографии отчетов, сканы документов, видеозаписи приемки товара — стандартный механизм обмена 1С начинает давать сбои. Причина кроется в том, что по умолчанию платформа сериализует бинарные данные в формат Base64 и помещает их внутрь единого монолитного XML-файла. На медленных и нестабильных каналах связи (GPRS, 3G/4G-модемы с низким уровнем сигнала) передача такого файла размером в десятки и сотни мегабайт становится практически невозможной: постоянные обрывы сессии приводят к повреждению архивов и бесконечным повторным попыткам выгрузки.
В рамках этой статьи мы детально проанализируем архитектурные подходы и технические решения, позволяющие обойти ограничения платформы, разгрузить транспортные каналы и гарантировать доставку документов и присоединенных файлов в центральную базу даже в самых неблагоприятных условиях связи.
Давайте разберем, как устроен типовой обмен данными на базе планов обмена или БСП (Библиотеки стандартных подсистем). При регистрации изменений объектов система формирует единое сообщение обмена. Если в документе содержится реквизит с типом ХранилищеЗначения, хранящий тяжелую картинку, при выгрузке этот бинарный поток преобразуется в текстовую строку Base64. В результате:
Ниже мы подробно рассмотрим несколько эффективных стратегий решения этой проблемы, которые позволяют оптимизировать производительность и повысить стабильность синхронизации.
Это наиболее надежный архитектурный паттерн. Его суть заключается в том, чтобы полностью исключить бинарные данные из основного контура обмена. Через стандартный план обмена передаются только легкие XML-данные (реквизиты документов, табличные части и метаданные присоединенных файлов), а сами файлы отправляются параллельно по отдельному, более приспособленному каналу.
Разберем по шагам, как реализовать этот механизм:
Файлы или регистр сведений ДвоичныеДанныеФайлов).Очень часто пользователи фотографируют документы на смартфоны с высоким разрешением камеры, в результате чего одна фотография весит от 5 до 15 МБ. Для большинства бизнес-задач (например, подтверждение факта отгрузки товара) такая детализация избыточна. Ограничение разрешения изображения до 1024x768 пикселей и сжатие качества JPEG до 70% уменьшает объем файла в 10–20 раз практически без потери читаемости текста.
Посмотрим на пример кода, реализующего программное сжатие изображения встроенными средствами платформы 1С:
Функция СжатьИзображение(ИсходныйДвоичныйОбъект, МаксимальнаяШирина = 1024, КачествоСжатия = 70) Экспорт
Попытка
КартинкаОбъект = Новый Картинка(ИсходныйДвоичныйОбъект);
// Проверяем, требуется ли масштабирование
Ширина = КартинкаОбъект.Ширина();
Высота = КартинкаОбъект.Высота();
Если Ширина > МаксимальнаяШирина Тогда
Коэффициент = МаксимальнаяШирина / Ширина;
НоваяШирина = МаксимальнаяШирина;
НоваяВысота = Цел(Высота * Коэффициент);
// Выполняем масштабирование картинки
КартинкаОбъект = КартинкаОбъект.Преобразовать(ФорматКартинки.JPEG, НоваяШирина, НоваяВысота);
Иначе
// Если ресайз не нужен, просто преобразуем для изменения качества
КартинкаОбъект = КартинкаОбъект.Преобразовать(ФорматКартинки.JPEG);
КонецЕсли;
// Получаем сжатые двоичные данные
Возврат КартинкаОбъект.ПолучитьДвоичныеДанные();
Исключение
ЗаписатьЛогОшибок("Ошибка сжатия картинки: " + ОписаниеОшибки());
Возврат ИсходныйДвоичныйОбъект;
КонецПопытки;
КонецФункции
Этот код целесообразно вызывать в обработчике перед записью файла в периферийной базе. Сжатие должно происходить асинхронно или в фоновом задании, чтобы не заставлять пользователя ждать завершения процесса обработки в интерфейсе.
Если бизнес-логика требует жесткого контроля доставки каждого документа вместе с его файлами в рамках одной транзакции, стандартный механизм выгрузки всего плана обмена в один файл не подходит. Мы можем самостоятельно написать обработку выгрузки, которая будет дробить изменения на отдельные пакеты.
Проанализируем пример кода, выполняющего выгрузку документов по одному файлу на каждый документ:
Процедура ВыгрузитьИзмененияПодокументно(УзелОбмена) Экспорт
// Получаем зарегистрированные изменения для конкретного узла
ВыборкаИзменений = ПланыОбмена.ВыбратьИзменения(УзелОбмена, НомерСообщения);
Пока ВыборкаИзменений.Следующий() Цикл
ОбъектИзменения = ВыборкаИзменений.Получить();
// Нас интересуют только документы конкретного типа со специфическим статусом
Если ТипЗнч(ОбъектИзменения) = Тип("ДокументОбъект.УправлениеОтгрузкой") Тогда
Если ОбъектИзменения.Статус = Перечисления.СтатусыОтгрузки.ГотовКОтправке Тогда
// Начинаем формирование индивидуального XML-пакета
ИмяФайлаПакета = ПолучитьИмяФайлаПакета(ОбъектИзменения.Ссылка);
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл(ИмяФайлаПакета);
ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();
ЗаписьСообщения.НачатьЗапись(ЗаписьXML, УзелОбмена);
// Выгружаем конкретный объект в XML
ЗаписатьXML(ЗаписьXML, ОбъектИзменения);
// Если у документа есть файлы, упаковываем их в ZIP вместе с XML
АрхивироватьПакетСКартинками(ИмяФайлаПакета, ОбъектИзменения.Ссылка);
ЗаписьСообщения.ЗакончитьЗапись();
ЗаписьXML.Закрыть();
// Отправляем сформированный архив на FTP/HTTP-сервер
Если ОтправитьПакетНаТранспорт(ИмяФайлаПакета) Тогда
// Снимаем регистрацию изменений только для этого конкретного объекта
ПланыОбмена.УдалитьРегистрациюИзменений(УзелОбмена, ОбъектИзменения.Ссылка);
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Использование схемы «1 документ = 1 пакет» гарантирует, что даже на самом плохом канале связи документ небольшого размера (вместе со сжатыми фото) успешно загрузится за один короткий сеанс связи. Если сессия прервется, система повторит отправку только этого конкретного документа, а не всей базы за прошедший месяц.
Использование FTP-протокола на нестабильных мобильных сетях часто приводит к появлению "битых" файлов нулевого размера. HTTP-сервисы предоставляют гораздо более гибкие возможности по контролю целостности передаваемых пакетов.
При передаче файлов через специально разработанный HTTP-сервис в центральной базе мы можем реализовать следующий алгоритм контроля:
200 OK.Для совсем критических условий связи можно реализовать блочную (чанковую) загрузку файлов, когда файл перед отправкой разбивается на части по 256–512 килобайт, и каждая часть отправляется независимо. После получения всех блоков центральная база собирает их обратно в один файл. Это полностью исключает проблему потери прогресса загрузки при обрывах связи.
Для создания отказоустойчивой системы обмена данными в условиях нестабильного мобильного соединения рекомендуем придерживаться комплексного подхода:
Картинка платформы 1С для программного сжатия изображений до приемлемого разрешения перед их отправкой.