В современной разработке на платформе 1С переход с COM-соединений на Web-сервисы (SOAP) или HTTP-сервисы становится необходимостью. Основными драйверами этого процесса выступают переход на операционные системы семейства Linux, где COM не поддерживается, и потребность в более гибкой архитектуре. Однако простая замена строк кода не всегда дает ожидаемый прирост производительности. В этой статье мы подробно разберем, как правильно перевести механизмы интеграции на Web-сервисы, проанализируем статистику выполнения запросов и научимся обходить «подводные камни» сериализации данных.
Традиционно COM-соединение использовалось для обмена данными между базами 1С благодаря простоте реализации: программист мог обращаться к объектам удаленной базы так же, как к локальным. Главный минус этой технологии — колоссальные временные затраты на инициализацию соединения. Создание COM-объекта требует запуска полноценного сеанса на стороне сервера Windows, что может занимать от 10 до 30 секунд.
Рассмотрим результаты замеров времени инициализации:
Таким образом, для частых коротких запросов Web-сервисы выигрывают «всухую». Однако при работе с тяжелыми отчетами ситуация меняется, и мы разберем, почему это происходит.
Рассмотрим стандартную ситуацию: нам нужно получить данные из филиала. Если раньше мы использовали выборку из запроса через COM, то теперь мы будем получать готовую таблицу значений, сериализованную в XDTO. Рассмотрим, как изменяется код на стороне клиента.
Было (через COM-соединение):
РезОбразцы = ЗапросОбразцы.Выполнить();
ВыборкаОбразцы = РезОбразцы.Выбрать();
Пока ВыборкаОбразцы.Следующий() Цикл
ОбработкаПрерыванияПользователя();
стрТЗ = тзОбразцы.Добавить();
ЗаполнитьЗначенияСвойств(стрТЗ, ВыборкаОбразцы);
стрТЗ.НаименованиеБД = стрБД.НаименованиеБД;
КонецЦикла;
Стало (через Web-сервис):
// Выполняем запрос через прокси-функцию, которая возвращает ТаблицуЗначений
РезОбразцы = глЗапрос(Префикс, ЗапросОбразцы);
// Обход уже готовой таблицы значений
Для каждого ВыборкаОбразцы Из РезОбразцы Цикл
ОбработкаПрерыванияПользователя();
стрТЗ = тзОбразцы.Добавить();
ЗаполнитьЗначенияСвойств(стрТЗ, ВыборкаОбразцы);
стрТЗ.НаименованиеБД = стрБД.НаименованиеБД;
КонецЦикла;
Заметим, что в случае с Web-сервисом мы избавляемся от последовательного чтения данных через Следующий(), что уменьшает количество «походов» к удаленной базе. Все данные передаются одним пакетом.
Главная причина, по которой Web-сервис может работать медленнее COM на больших выборках — это накладные расходы на сериализацию данных в XML формат. Когда СериализаторXDTO встречает в результате запроса ссылку (например, СправочникСсылка.Номенклатура), он пытается выгрузить информацию о ней. Если же в запросе используются обращения через точку (например, ДокументПродажи.Контрагент.Наименование), платформа выполняет неявные соединения на стороне сервера, что существенно замедляет выполнение SQL-запроса.
Проанализируем пример неудачного запроса для Web-сервиса:
ТекстЗапроса = "ВЫБРАТЬ
| ФактПродажи.Период КАК ПериодМесяц,
| ФактПродажи.Номенклатура.Наименование КАК НоменклатураНаименование,
| ФактПродажи.СуммаПродажи КАК Сумма,
| ФактПродажи.ДокументПродажи.Контрагент КАК Контрагент
|ИЗ
| РегистрНакопления.Продажи.Обороты(&Дата1, &Дата2) КАК ФактПродажи";
В данном случае поле Контрагент является ссылкой. При передаче 100 000 строк через Web-сервис XML-пакет станет огромным, так как для каждой ссылки будет формироваться описание типа. В COM это работает быстрее, так как передается внутренний идентификатор 1С.
Чтобы Web-сервис работал эффективно, мы должны придерживаться правила: передавать только простые типы (Строка, Число, Дата, Булево). Если нам нужны данные из связанных справочников, их нужно получать прямо в запросе, а ссылки преобразовывать в строки (Наименование или Код) или Уникальные Идентификаторы.
Разберем правильную оптимизацию через ВЫРАЗИТЬ и левые соединения:
Вместо обращения к составному типу ДокументПродажи.Контрагент, выполним явное приведение типов и получим наименование сразу.
ТекстЗапроса = "ВЫБРАТЬ
| ВложенныйЗапрос.ПериодМесяц,
| ВложенныйЗапрос.НоменклатураНаименование,
| СУММА(ВложенныйЗапрос.Сумма) КАК Сумма,
| ВложенныйЗапрос.КонтрагентНаименование
|ИЗ
| (ВЫБРАТЬ
| Продажи.Период КАК ПериодМесяц,
| Продажи.Номенклатура.Наименование КАК НоменклатураНаименование,
| Продажи.СуммаОборот КАК Сумма,
| ВЫРАЗИТЬ(Продажи.ДокументПродажи КАК Документ.РеализацияТоваров).Контрагент.Наименование КАК КонтрагентНаименование
| ИЗ
| РегистрНакопления.Продажи.Обороты(&Дата1, &Дата2) КАК Продажи
| ГДЕ
| Продажи.ДокументПродажи ССЫЛКА Документ.РеализацияТоваров) КАК ВложенныйЗапрос
|СГРУППИРОВАТЬ ПО
| ВложенныйЗапрос.ПериодМесяц,
| ВложенныйЗапрос.НоменклатураНаименование,
| ВложенныйЗапрос.КонтрагентНаименование";
Результаты такой оптимизации впечатляют:
Проанализируем критический порог, после которого COM начинает выигрывать у Web. Это происходит на очень больших выборках данных (свыше 150 000 – 200 000 строк или более 80 Мб в текстовом эквиваленте).
Сравнение при выборке в 216 000 строк:
Мы видим, что на сверхбольших объемах XDTO-сериализатор тратит слишком много времени на упаковку данных в XML (65 секунд против 10 секунд работы SQL). Но учитывая, что COM — это технология прошлого, для таких объемов рекомендуется использовать HTTP-сервисы с передачей данных в формате JSON или порционную выгрузку.
Для того чтобы сделать переход максимально бесшовным, на стороне удаленной базы (филиала) создается универсальный Web-сервис. Рассмотрим пример реализации функции, которая принимает текст запроса и параметры, а возвращает ОбъектXDTO (таблицу значений).
Функция ВыполнитьЗапрос(ТекстЗапроса, СериализованныеПараметры)
Сериализатор = Новый СериализаторXDTO(ФабрикаXDTO);
// Распаковываем параметры запроса (структуру)
ПараметрыЗапроса = Сериализатор.ПрочитатьXDTO(СериализованныеПараметры);
Запрос = Новый Запрос(ТекстЗапроса);
Для каждого ТекПараметр Из ПараметрыЗапроса Цикл
Запрос.УстановитьПараметр(ТекПараметр.Ключ, ТекПараметр.Значение);
КонецЦикла;
// Выполняем и выгружаем в ТЗ
РезультатТЗ = Запрос.Выполнить().Выгрузить();
// Сериализуем всю таблицу целиком для передачи
Возврат Сериализатор.ЗаписатьXDTO(РезультатТЗ);
КонецФункции
Проанализировав ситуацию, мы можем сформулировать следующие правила для успешной замены COM на Web-сервисы:
COM позволял делать мелкие запросы в цикле (хоть это и было медленно), то для Web-сервисов это фатально. Старайтесь собрать все данные одним тяжелым запросом на стороне сервера удаленной базы и передать их одним пакетом.Web-сервисах между вызовами методов состояние менеджера временных таблиц не сохраняется. Весь пакет запросов (помещение во ВТ, работа с ними, уничтожение) должен находиться внутри одного текста запроса, передаваемого в метод сервиса.ВЫБРАТЬ и в параметрах ГДЕ используйте Наименование, Код или УникальныйИдентификатор(). Это радикально сократит объем XML-пакета и ускорит сериализацию.Тзап (время выполнения запроса), которое при работе через веб-сервер становится критичным.WSПрокси при каждом обращении. Если вы опрашиваете 8 филиалов, создайте прокси один раз и храните их в кэше (например, в параметрах сеанса или глобальной переменной), пока сеанс пользователя активен.Переход на Web-сервисы — это не просто смена синтаксиса, а изменение подхода к проектированию запросов. Следуя этим рекомендациям, вы сможете не только сохранить работоспособность системы при переходе на Linux, но и значительно ускорить получение данных за счет быстрого подключения и пакетной передачи данных.