Как правильно завершить HTTP соединение в 1С и избежать зависания ресурсов

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

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

Разбираем механизм работы пула соединений

Для начала проанализируем, почему команда Соединение = Неопределено; не всегда приводит к немедленному разрыву сетевого сокета. Платформа 1С:Предприятие оптимизирована для высокой производительности, поэтому она использует так называемый пул соединений (Connection Pooling). Это означает, что после завершения обмена данными физическое TCP-соединение не разрывается сразу, а помещается в кэш. Если в ближайшее время (обычно в течение 60 секунд) программа снова обратится к тому же серверу, платформа использует уже открытый канал, экономя время на «рукопожатии» (handshake) и установке защищенного TLS-соединения.

Рассмотрим ситуацию с точки зрения операционной системы. Когда мы создаем объект HTTPСоединение, системные библиотеки (WinHTTP в Windows или libcurl в Linux) открывают порт. После уничтожения объекта в коде 1С, сокет может оставаться в состоянии TIME_WAIT или ESTABLISHED еще некоторое время. Выясним причину: это поведение заложено на уровне реализации стека TCP/IP для предотвращения ошибок при передаче задержавшихся пакетов данных.

Использование заголовка Connection: close

Если наша задача — гарантированно сообщить серверу, что мы не планируем использовать это соединение повторно, мы должны использовать стандартные средства протокола HTTP/1.1. По умолчанию в 1С используется режим Keep-Alive, который поддерживает соединение активным. Разберем по шагам, как принудительно инициировать закрытие соединения со стороны клиента.

Для этого нам необходимо добавить специальный заголовок в объект HTTPЗапрос. Посмотрим на пример кода:


Сервер = "api.mysite.com";
Соединение = Новый HTTPСоединение(Сервер);

Запрос = Новый HTTPЗапрос("/v1/data");
// Явно указываем серверу, что соединение нужно закрыть после ответа
Запрос.Заголовки.Вставить("Connection", "close");

Ответ = Соединение.ВызватьHTTPМетод("GET", Запрос);

При получении такого заголовка удаленный сервер после отправки данных сам инициирует процедуру закрытия сокета. Это самый правильный способ с точки зрения сетевых стандартов, если вы делаете разовый запрос к ресурсу и не хотите плодить «спящие» соединения.

Управление сеансами 1С через заголовок IBSession

Часто возникает путаница между сетевым соединением (портом) и логическим сеансом в информационной базе 1С — решать задачу контроля ресурсов удобнее через обработка управления сеансами и соединениями 1С. Если вы обращаетесь к другой базе 1С через HTTP-сервисы, то даже после закрытия сетевого сокета на сервере может остаться висеть сеанс пользователя. Проанализируем решение этой проблемы.

Для завершения сеанса в информационной базе 1С необходимо использовать заголовок IBSession с директивой finish — для этого пригодится обработка завершения сеансов и освобождения ресурсов. Это особенно актуально при отладке, когда каждый новый запрос создает новую сессию, занимающую лицензию и память. Рассмотрим пример реализации:


Запрос = Новый HTTPЗапрос("/hs/my_service/get_data");
// Указываем платформе 1С на стороне сервера завершить сеанс после обработки
Запрос.Заголовки.Вставить("IBSession", "finish");

Ответ = Соединение.ОтправитьДляОбработки(Запрос);

Важный момент: данный заголовок работает только при обращении к веб-сервисам или HTTP-сервисам, опубликованным на платформе 1С. При работе со сторонними ресурсами (например, API банков или соцсетей) этот заголовок будет проигнорирован.

Настройка таймаутов и область видимости

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

  1. Ограничение области видимости: Создавайте объект соединения только внутри локальных процедур или функций. Как только выполнение кода выйдет из функции, локальная переменная будет помечена сборщиком мусора, и ресурсы начнут освобождаться автоматически. Не используйте глобальные переменные модуля или реквизиты формы для хранения HTTPСоединение без явной необходимости.
  2. Сокращение таймаута: При создании объекта можно указать время ожидания. Если сервер не отвечает или соединение простаивает, оно будет закрыто быстрее.

Пример настройки таймаута:


// Установим таймаут в 10 секунд вместо стандартных 60
Таймаут = 10;
Соединение = Новый HTTPСоединение(ИмяСервера, , , , , Таймаут);

Влияние настроек веб-сервера

Выясним причину, по которой даже идеальный код на стороне 1С может не помогать. Иногда проблема кроется в настройках веб-сервера (IIS или Apache), на котором опубликован сервис. В настройках веб-сервера есть параметры KeepAliveTimeout (для Apache) или Connection Timeout (для IIS). Если эти значения слишком велики (например, несколько минут), то сервер будет принудительно держать соединение открытым, ожидая новых данных от клиента.

Если вы являетесь администратором системы, проверьте следующие настройки:

Подведем итоги

Мы проанализировали основные способы завершения HTTP-соединений — для этих задач есть готовый инструментарий для управления заданиями и отладки. В большинстве случаев штатное поведение платформы 1С с использованием пула соединений является оптимальным, так как оно экономит ресурсы на повторную авторизацию. Однако при необходимости принудительного разрыва следует комбинировать установку заголовка Connection: close, использование заголовка IBSession: finish для сервисов 1С и правильное управление временем жизни локальных переменных.

Помните, что полное мгновенное закрытие всех сокетов в состоянии TIME_WAIT на уровне операционной системы практически невозможно средствами встроенного языка 1С, так как это часть низкоуровневой работы сетевого стека, призванная обеспечить надежность передачи данных.

← На главную