При интеграции различных систем на базе 1С:Предприятие часто возникает задача получения оперативных данных, например, остатков товаров или цен из другой информационной базы. Использование метода GET для получения данных по одному объекту (через передачу идентификатора в параметрах строки запроса) удобно и просто в реализации, однако оно перестает быть эффективным, когда количество объектов исчисляется сотнями или тысячами. Выполнение 100 отдельных HTTP-запросов в цикле создаст огромную нагрузку на сеть и сервер, а также значительно увеличит время ожидания для пользователя.
В данной статье мы разберем, как оптимизировать этот процесс, реализовав пакетную передачу данных в одном запросе. Мы рассмотрим использование метода POST, работу с форматом JSON, сериализацию данных и методы оптимизации на стороне базы-источника.
Для начала проанализируем ситуацию: почему GET нам не подходит для пакетной передачи? Основное ограничение GET заключается в том, что параметры передаются в URL-строке, которая имеет лимит по длине. Кроме того, передавать сложные структуры данных через параметры строки крайне неудобно.
Решением является использование метода POST. В этом случае данные передаются не в заголовке или строке адреса, а в теле (body) запроса. Это позволяет передать практически неограниченный объем информации в структурированном виде (например, JSON или XML).
Рассмотрим наиболее популярный и универсальный способ обмена — формат JSON. Если в вашей табличной части 100 строк, содержащих ссылки на номенклатуру и характеристики, напрямую передать объект ТаблицаЗначений через ЗаписатьJSON() не получится, так как этот объект не является сериализуемым по умолчанию для данного метода.
Выясним, как правильно подготовить данные для отправки. Самый надежный способ — преобразовать таблицу в Массив, состоящий из Структур. Разберем по шагам, как это реализовать:
// Создаем массив для хранения данных строк
СписокТоваров = Новый Массив;
Для Каждого СтрокаТЧ Из Объект.Товары Цикл
ДанныеТовара = Новый Структура;
ДанныеТовара.Вставить("НоменклатураGUID", Строка(СтрокаТЧ.Номенклатура.УникальныйИдентификатор()));
ДанныеТовара.Вставить("ХарактеристикаGUID", Строка(СтрокаТЧ.Характеристика.УникальныйИдентификатор()));
СписокТоваров.Добавить(ДанныеТовара);
КонецЦикла;
// Сериализуем массив в строку JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, СписокТоваров);
СтрокаЗапроса = ЗаписьJSON.Закрыть();
В данном примере мы преобразуем ссылки 1С в их строковое представление GUID. Это гарантирует, что на стороне получателя мы сможем однозначно идентифицировать объекты, даже если типы данных в базах различаются. Использование Структуры позволяет легко добавлять новые поля (например, склад или количество) без изменения логики парсинга.
Теперь проанализируем, как эффективно обработать полученный массив на стороне HTTP-сервиса (базы-источника остатков). Получив JSON, мы десериализуем его обратно в массив структур. Чтобы запрос к базе данных отработал максимально быстро, крайне не рекомендуется выполнять поиск остатков в цикле.
Вместо этого мы применим следующий алгоритм:
РегистрНакопления.ТоварыНаСкладах.Остатки.Посмотрим на пример формирования запроса на стороне сервера:
// Предположим, МассивДанных получен из ЧтенияJSON
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВТ_Данные.НоменклатураGUID КАК НоменклатураGUID,
| ВТ_Данные.ХарактеристикаGUID КАК ХарактеристикаGUID
|ПОМЕСТИТЬ ВТ_Запрос
|ИЗ
| &ТЗ_Данные КАК ВТ_Данные
|;
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ТоварыНаСкладахОстатки.КоличествоОстаток КАК Остаток,
| ВТ_Запрос.НоменклатураGUID КАК НоменклатураGUID,
| ВТ_Запрос.ХарактеристикаGUID КАК ХарактеристикаGUID
|ИЗ
| ВТ_Запрос КАК ВТ_Запрос
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(
| ,
| (Номенклатура.УникальныйИдентификатор, Характеристика.УникальныйИдентификатор) В
| (ВЫБРАТЬ
| ВТ.НоменклатураGUID,
| ВТ.ХарактеристикаGUID
| ИЗ
| ВТ_Запрос КАК ВТ)) КАК ТоварыНаСкладахОстатки
| ПО ВТ_Запрос.НоменклатураGUID = ТоварыНаСкладахОстатки.Номенклатура.УникальныйИдентификатор";
Важный момент: поиск по строковому представлению GUID в больших базах может быть медленным. Если производительность критична, рекомендуется предварительно конвертировать строковые GUID в ссылки в самой базе-источнике или использовать соответствия (Maps).
Если обе базы являются базами 1С и имеют идентичные или схожие структуры, рассмотрим метод передачи через ХранилищеЗначения. Этот способ позволяет передать объект ТаблицаЗначений целиком, сохраняя типизацию колонок и используя встроенное сжатие данных.
Разберем процесс по шагам:
ХранилищеЗначения с максимальным сжатием.ДвоичныеДанные из хранилища.POST-запроса.
// Код на стороне отправителя
Хранилище = Новый ХранилищеЗначения(ТаблицаТоваров, Новый СжатиеДанных(9));
ДвоичныеДанныеТела = Хранилище.Получить();
// Далее передаем ДвоичныеДанныеТела в HTTPЗапрос.УстановитьТелоИзДвоичныхДанных()
Этот метод считается одним из самых быстрых для сценария "1С -> 1С", так как исключает стадию текстового парсинга JSON или XML.
Проанализируем еще несколько технических нюансов, которые помогут сделать ваш HTTP-сервис профессиональным:
1. Сжатие GZIP. Если вы передаете очень большие списки (тысячи строк), объем текстового JSON может быть значительным. Используйте сжатие GZIP. В 1С это реализуется через объект ЗаписьДанных и СжатиеДанных. Большинство современных HTTP-сервисов умеют прозрачно работать со сжатым контентом, если указаны соответствующие заголовки Content-Encoding: gzip.
2. Использование соответствий (Соответствие). Как было предложено в обсуждении, на стороне отправителя можно сформировать Соответствие, где ключом будет комбинированная строка "GUID_Номенклатуры + GUID_Характеристики", а значением — необходимый параметр. Объект Соответствие нативно сериализуется в 1С и удобен для быстрого поиска значения по ключу после получения ответа.
3. Обработка ошибок. Всегда проектируйте структуру ответа так, чтобы она содержала статус выполнения. Например, возвращайте структуру с полями Success (булево) и Data (массив результатов). Это позволит вызывающей базе корректно обработать ситуацию, когда, например, по части товаров остатки найдены, а по части — произошла ошибка в данных.
Подводя итог, можно сказать, что для получения данных по списку товаров оптимальным выбором будет POST-запрос с передачей массива структур в формате JSON. Это обеспечивает гибкость, наглядность при отладке и высокую скорость работы за счет минимизации количества сетевых вызовов.