При организации взаимодействия между двумя базами 1С через веб-сервисы разработчики часто сталкиваются с проблемой: сам код сервиса отрабатывает мгновенно (например, за 0.5 секунды), но общее время ожидания ответа клиентом составляет 2–5 секунд. Проанализируем ситуацию: основная часть времени тратится не на выполнение бизнес-логики, а на инфраструктурные задачи — установку соединения, авторизацию и инициализацию сеанса на стороне сервера-источника. В этой статье мы подробно разберем, как минимизировать эти задержки и сделать обмен данными максимально быстрым.
Рассмотрим подробнее, что происходит в момент вызова веб-сервиса. Когда база-клиент обращается к веб-серверу (Apache или IIS), тот передает запрос расширению 1С. Платформа должна создать новый сеанс (или использовать существующий из пула), проверить лицензию и выполнить процедуру УстановкаПараметровСеанса в модуле сеанса. Если конфигурация тяжелая, а модуль сеанса перегружен проверками прав и заполнением глобальных параметров, это может занимать несколько секунд при каждом запросе.
Выясним причину долгого старта. Перед каждым вызовом веб-сервиса или HTTP-сервиса 1С выполняет стандартный запуск сеанса. Если в модуле сеанса прописана сложная инициализация для обычных пользователей, она будет срабатывать и для технических учетных записей веб-сервисов. Проанализируем код и добавим условие, позволяющее пропускать лишние действия для сервисных соединений.
Для определения типа соединения воспользуемся методом ПолучитьТекущийСеансИнформационнойБазы().ИмяПриложения. Разберем пример кода в модуле сеанса:
Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
// Проверяем, является ли текущее соединение вызовом веб-сервиса или HTTP-сервиса
ТекущийСеанс = ПолучитьТекущийСеансИнформационнойБазы();
ИмяПриложения = ТекущийСеанс.ИмяПриложения;
Если ИмяПриложения = "WebClient" Или ИмяПриложения = "WebServerExtension" Тогда
// Для веб-сервисов инициализируем только КРИТИЧЕСКИ необходимые параметры
// Это позволит сократить время входа в систему до долей секунды
ИнициализироватьМинимальныйНаборПараметров(ТребуемыеПараметры);
Возврат;
КонецЕсли;
// Стандартная инициализация для обычных пользователей
ПолнаяИнициализацияПараметров(ТребуемыеПараметры);
КонецПроцедуры
Посмотрим на настройки публикации. По умолчанию платформа может закрывать сеанс сразу после возврата ответа. Чтобы этого избежать и заставить 1С использовать уже открытый сеанс для следующего запроса, необходимо правильно настроить пул соединений в файле публикации default.vrd.
Найдем блок <pool> в файле и установим соответствующие параметры. Это позволит «удерживать» сеанс активным в течение некоторого времени, чтобы следующий запрос подхватил его мгновенно без повторной авторизации.
<point xmlns="http://v8.1c.ru/8.2/virtual-resource-system"
base="/MyBase"
ib="Srvr=MyServer;Ref=MyBase;">
<httpServices>
<service name="MyService" rootUrl="v1" enable="true" reuseSessions="use"/>
</httpServices>
<!-- Настройка пула соединений -->
<pool size="10" timeout="60" waitTimeout="5" />
</point>
Здесь параметр size определяет максимальное количество удерживаемых сеансов, а timeout — время в секундах, в течение которого сеанс будет ждать нового запроса перед закрытием. Использование параметра reuseSessions="use" (или autouse) в описании сервиса также критически важно для повторного использования сеансов.
Рассмотрим ситуацию на стороне базы-клиента. Часто разработчики создают объект WSПрокси или HTTPСоединение непосредственно перед вызовом и уничтожают его сразу после. Посмотрим, как можно оптимизировать этот процесс, сохраняя объект соединения в переменной модуля управляемого приложения.
Создадим экспортную переменную и метод для получения «живого» соединения:
// В модуле управляемого приложения
Перем ГлобальноеСоединениеЭкспорт;
Функция ПолучитьПроксиСервиса() Экспорт
Если ГлобальноеСоединениеЭкспорт = Неопределено Тогда
// Инициализируем соединение один раз при первом обращении
Определение = Новый WSОпределения("http://server/base/ws/service?wsdl", "User", "Pass");
ГлобальноеСоединениеЭкспорт = Новый WSПрокси(Определение, "http://uri", "ServiceName", "EndpointName");
КонецЕсли;
Возврат ГлобальноеСоединениеЭкспорт;
КонецФункции
Важный момент: если вы используете SOAP (веб-сервисы), чтение WSDL-описания из сети при каждом создании WSОпределения — очень дорогая операция. Рекомендуется сохранить wsdl-файл локально на диске и инициализировать объект из локального файла, либо использовать статические WS-ссылки, добавленные в дерево конфигурации.
Проанализируем разницу между протоколами. SOAP (Web-сервисы в 1С) использует XML и строгое описание типов XDTO. Это накладывает дополнительные расходы на парсинг больших XML-пакетов и проверку типов. HTTP-сервисы работают с «голым» протоколом HTTP, что позволяет передавать данные в формате JSON. Как показывает практика, HTTP-сервисы в 1С работают в 1.5–2 раза быстрее за счет отсутствия тяжелой надстройки XDTO.
Для передачи данных между базами 1С через HTTP-сервис удобно использовать встроенные средства сериализации JSON. Посмотрим на пример отправки запроса:
Соединение = Новый HTTPСоединение("server", , "User", "Pass");
Запрос = Новый HTTPЗапрос("/base/hs/v1/get_data");
Ответ = Соединение.Получить(Запрос);
Если Ответ.КодСостояния = 200 Тогда
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
Результат = ПрочитатьJSON(Чтение);
Чтение.Закрыть();
КонецЕсли;
Выясним, почему даже при правильном коде возникают задержки в 2–3 секунды. Проанализируем сетевые настройки сервера:
127.0.0.1 вместо localhost или явно отключите IPv6 в настройках адаптера.default.vrd) или в параметрах запуска веб-сервера выключена отладка. Включенная отладка веб-сервисов может замедлять каждый вызов на 1–2 секунды.Подведем итог нашему анализу. Для достижения максимальной скорости работы сервисов необходимо придерживаться комплексного подхода:
default.vrd, чтобы сеансы жили дольше одного вызова.УстановкаПараметровСеанса для технических пользователей.WSПрокси через локальный WSDL или WS-ссылку.Соблюдение этих правил позволяет сократить время отклика с 5 секунд до комфортных 100–300 миллисекунд, что критически важно для интерактивных действий пользователей в интерфейсе.