Почему веб-сервис 1С после длительного выполнения не возвращает управление клиенту?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При организации обмена данными между базами 1С через SOAP веб-сервисы разработчики нередко сталкиваются с ситуацией: небольшие пакеты данных обрабатываются мгновенно, но при передаче объемного пакета клиентская база зависает. В журнале регистрации или логах сервера видно, что экспортная функция веб-сервиса успешно отработала и вернула результат, однако клиент так и не получает управление обратно, продолжая ожидать ответа вплоть до ошибки «Превышен таймаут операции».

Разберем природу этого поведения, выясним причины сбоя на сетевом и прикладном уровнях, а также рассмотрим практические способы решения проблемы.

В чем причина зависания при длительном синхронном вызове

Проанализируем механику взаимодействия клиента и веб-сервиса. Когда мы вызываем метод сервиса через объект WSПрокси, клиент отправляет HTTP-запрос и переходит в режим блокирующего ожидания ответа по установленному TCP-соединению:


Прокси = ПолучитьПрокси();
ДанныеОбмена = СформироватьПакетОбмена(Узел);

// Вызов зависает на длительное время:
Прокси.ЗаписатьДанные(КодЭтогоУзла, ДанныеОбмена);

Если серверная процедура выполняется 20–30 минут, соединение оказывается в состоянии простоя (idle): по сокету не передаются пакеты с полезными данными. Это приводит к следующим системным проблемам:

  1. Сброс соединения промежуточным сетевым оборудованием: маршрутизаторы, межсетевые экраны (брандмауэры) и таблицы трансляции NAT имеют собственные таймауты неактивности соединений (обычно от 5 до 15 минут). Если в канале нет трафика, сетевой шлюз молча удаляет запись о трансляции сокета без отправки пакетов TCP RST или FIN. Сервер завершает транзакцию и отправляет ответ в уже разорванный канал, а клиент продолжает ждать ответа до истечения локального таймаута.
  2. Таймауты веб-сервера и пула приложений: веб-серверы Apache и IIS обладают собственными ограничениями на длительность соединения. В IIS таймаут простоя пула приложений (Idle Time-out) по умолчанию составляет 20 минут. Если ответ от модуля расширения 1С задерживается, веб-сервер прерывает соединение с клиентом, хотя рабочий процесс rphost может продолжать выполнение кода.
  3. Таймауты пула соединений в 1С: для веб-сервисов в платформе 1С предусмотрен пул соединений. По умолчанию время жизни соединения в пуле ограничено 1200 секундами (20 минут). При превышении этого порога без межузлового трафика связь между модулем веб-сервера и кластером серверов 1С может быть нарушена.

Решение 1. Переход на асинхронную модель обработки (Рекомендуемое)

Держать открытым синхронное HTTP/SOAP-соединение более 1–2 минут — грубая архитектурная ошибка. Правильный подход заключается в разделении вызова на прием данных и их отложенную обработку в фоновом режиме.

Разберем по шагам реализацию асинхронного взаимодействия:

  1. Быстрый прием пакета: клиент передает сжатые данные. Сервер веб-сервиса сохраняет их в регистр сведений или во временное хранилище базы, не выполняя разбор данных в основном потоке веб-вызова.
  2. Запуск фонового задания: сервер инициирует асинхронное фоновое задание через менеджер фоновых заданий, которое выполняет длительную загрузку данных.
  3. Мгновенный возврат идентификатора: веб-сервис сразу же возвращает клиенту уникальный идентификатор запущенного задания (УникальныйИдентификатор). Соединение закрывается за пару секунд.
  4. Периодический опрос состояния: клиентская база в цикле (или регламентным заданием) периодически обращается к отдельному легковесному методу веб-сервиса с вопросом: «Готовы ли данные для задания с переданным GUID?».

Посмотрим на пример серверной реализации метода веб-сервиса:


Функция ЗаписатьДанныеАсинхронно(КодУзла, Данные) Экспорт
    
    // Сохраняем пакет в базу (например, во временную таблицу или регистр)
    ИдентификаторЗадания = СохранитьПакетВоВременноеХранилище(КодУзла, Данные);
    
    // Параметры для фоновой процедуры
    ПараметрыЗадания = Новый Массив;
    ПараметрыЗадания.Добавить(ИдентификаторЗадания);
    ПараметрыЗадания.Добавить(КодУзла);
    
    // Запускаем тяжелую обработку в фоне
    ФоновыеЗадания.Выполнить("ИнтеграцияСервер.ВыполнитьФоновуюЗагрузку", ПараметрыЗадания, Строка(ИдентификаторЗадания), "Загрузка данных обмена");
    
    // Сразу возвращаем клиенту GUID операции
    Возврат Строка(ИдентификаторЗадания);
    
КонецФункции

На стороне клиента организуем периодическую проверку завершения операции:


Прокси = ПолучитьПрокси();
ИдентификаторЗадания = Прокси.ЗаписатьДанныеАсинхронно(КодЭтогоУзла, ДанныеОбмена);

// Ожидаем завершения без зависания основного соединения
Статус = "Выполняется";
Пока Статус = "Выполняется" Цикл
    // Пауза между опросами статуса (например, 10 секунд)
    ОжидатьЗавершения(10);
    
    Статус = Прокси.ПолучитьСтатусЗадания(ИдентификаторЗадания);
    Если Статус = "Ошибка" Тогда
        ВызватьИсключение "Ошибка фоновой обработки на сервере!";
    КонецЕсли;
КонецЦикла;

Решение 2. Разбиение пакета на пачки (чанкинг)

Если переделка логики на фоновые задания требует слишком больших трудозатрат, рассмотрим альтернативный вариант — пакетирование передаваемых данных. Вместо отправки одного монолитного файла, обработка которого занимает 30 минут, разобьем данные на стороне отправителя на небольшие порции (например, по 500–1000 документов).

Каждая порция отправляется отдельным запросом в рамках собственной короткой транзакции. Если при передаче одной из пачек возникнет сетевой сбой, нам не придется откатывать всю получасовую работу — достаточно будет повторить отправку упавшего пакета.

Решение 3. Настройка сетевой инфраструктуры и параметров пула

Если требуется временно обеспечить прохождение существующих тяжелых вызовов без изменения программного кода, необходимо скорректировать сетевые параметры серверов.

  1. Настройка TCP Keep-Alive в операционной системе: чтобы маршрутизаторы и сетевые экраны не сбрасывали сессию при отсутствии передачи данных, необходимо активировать регулярную отправку контрольных TCP-пакетов. В ОС Windows на клиентской машине и сервере веб-публикации в ветке реестра HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters скорректируем параметр KeepAliveTime, уменьшив его со стандартных 2 часов до 60 000–120 000 мс (1–2 минуты).
  2. Настройка параметров публикации default.vrd: в файле публикации веб-сервиса необходимо проконтролировать параметры пула соединений. Увеличим значение poolTimeout (время жизни соединения в пуле) и установим параметр reuseSessions="autouse" или reuseSessions="dontuse", чтобы избежать блокировок зависших сеансов при повторных вызовах.
  3. Таймаут прокси в коде 1С: убедимся, что при создании объекта WSПрокси в платформе 1С явно передается достаточный таймаут вызова (в секундах), перекрывающий максимальное время работы серверного кода:
    
    // Передаем таймаут в секундах (например, 3600 сек = 1 час) последним параметром
    Прокси = Новый WSПрокси(Определение, URIПространстваИмен, ИмяСервиса, ИмяТочкиПодключения, , 3600);
    

Подведем итог: зависание синхронного вызова при длительной обработке — это закономерный результат разрыва сетевых сокетов по таймауту неактивности. Наиболее надежным и стабильным решением всегда остается отказ от удержания открытого HTTP-соединения в пользу асинхронных фоновых заданий с получением статуса готовности.

← На главную