Разработка и Конфигурация · 12 мин
1С: как закрыть HTTP соединение и освободить ресурсы
Как правильно закрыть HTTPСоединение в 1С, освободить ресурсы, избежать утечек соединений и ошибок при обмене с веб-сервисами. Примеры кода и FAQ.
Объект HTTPСоединение во встроенном языке 1С используется для обмена данными с веб-сервисами, REST API, сайтами и внешними системами. Каждое такое соединение занимает сетевые ресурсы на клиенте и на сервере, и если им не управлять осознанно, со временем возникают зависания сеансов, ошибки «слишком много соединений» и утечки памяти в рабочих процессах сервера 1С.
Важный нюанс: у объекта HTTPСоединение нет явного метода Закрыть() или Close(). Это часто вызывает вопрос у разработчиков, привыкших к другим языкам. Освобождение ресурсов в 1С выполняется иначе — через разрыв ссылки на объект, работу сборщика мусора и корректную организацию кода обмена.
Ниже разобраны рабочие способы завершения HTTP-соединения, типичные сценарии обмена, ошибки, которые приводят к «зависшим» соединениям, и способы проверить, что ресурсы действительно освобождены.
Как устроено HTTP-соединение в 1С и почему нет метода Закрыть
Объект HTTPСоединение создается конструктором Новый HTTPСоединение(Сервер, Порт, ...) и представляет собой программную обертку над сетевым подключением. Фактическое TCP-соединение платформа устанавливает в момент первого вызова методов Получить, ОтправитьДляОбработки, Записать и других операций обмена.
Управление временем жизни объекта в 1С выполняет механизм подсчета ссылок и сборщик мусора. Пока на объект ссылается хотя бы одна переменная, он существует. Как только последняя ссылка исчезает — переменная выходит из области видимости или ей присваивается другое значение — объект становится кандидатом на удаление, и платформа освобождает связанные сетевые ресурсы.
Из этого следует главный практический вывод: «закрыть» HTTP-соединение в 1С означает разорвать ссылку на объект, а не вызвать специальный метод. Попытки найти в синтакс-помощнике метод Закрыть() у HTTPСоединение бесполезны — его там нет.
Базовый способ: присвоить переменной значение Неопределено
Самый прямой способ освободить соединение — после завершения обмена присвоить переменной, в которой хранится объект, значение Неопределено. После этого ссылка на объект теряется, и платформа может уничтожить его вместе с сетевым подключением.
HTTPСоединение = Новый HTTPСоединение("api.example.ru", 443,,,,, Новый ЗащищенноеСоединениеOpenSSL);
Запрос = Новый HTTPЗапрос("/v1/data");
Ответ = HTTPСоединение.Получить(Запрос);
// освобождаем соединение
HTTPСоединение = Неопределено;Обратите внимание: сборщик мусора не обязан уничтожить объект мгновенно после присваивания. На практике освобождение происходит быстро, но гарантировать точный момент нельзя. Для прикладного кода это не имеет значения — важно, что ресурс перестает удерживаться логикой программы.
Если переменная объявлена локально внутри процедуры или функции, присваивать Неопределено явно не обязательно: при выходе из процедуры локальные переменные уничтожаются, и ссылка пропадает сама. Явное обнуление имеет смысл, когда объект хранится в переменной модуля, в реквизите формы или в длительном цикле обмена.
Надежный шаблон обмена с Попытка...Исключение
Главная причина «утечек» соединений — прерывание кода по ошибке до того места, где объект освобождается. Если исключение возникает в середине обмена, строка HTTPСоединение = Неопределено просто не выполняется. Правильный шаблон использует конструкцию Попытка...Исключение...КонецПопытки.
Функция ПолучитьДанныеСервиса(АдресСервера)
HTTPСоединение = Неопределено;
Попытка
HTTPСоединение = Новый HTTPСоединение(АдресСервера, 443,,,, 30,
Новый ЗащищенноеСоединениеOpenSSL);
Запрос = Новый HTTPЗапрос("/api/status");
Ответ = HTTPСоединение.Получить(Запрос);
Если Ответ.КодСостояния = 200 Тогда
Возврат Ответ.ПолучитьТелоКакСтроку();
Иначе
ВызватьИсключение "Код ответа: " + Ответ.КодСостояния;
КонецЕсли;
Исключение
HTTPСоединение = Неопределено;
ВызватьИсключение ОписаниеОшибки();
КонецПопытки;
HTTPСоединение = Неопределено;
КонецФункцииКлючевые элементы шаблона: переменная инициализируется до блока Попытка, обнуление выполняется и в ветке ошибки, и после успешного завершения, а таймаут задается явно (в примере — 30 секунд). Без таймаута зависший сервер может удерживать соединение и сеанс 1С неоправданно долго.
Не глушите исключение пустым блоком Исключение КонецПопытки; — так вы потеряете информацию о причине сбоя и усложните диагностику. Минимум — записать ошибку в журнал регистрации через ЗаписьЖурналаРегистрации.
- 1Создайте HTTPСоединение с явным таймаутом внутри блока Попытка
- 2Выполните запрос и проверьте код состояния ответа
- 3В ветке Исключение обнулите переменную и зафиксируйте ошибку в журнале регистрации
- 4После успешного завершения присвойте переменной Неопределено
- 5Убедитесь, что объект не сохраняется в глобальных переменных или реквизитах формы без необходимости
Создавать новое соединение или переиспользовать существующее
Частый вопрос — что лучше: держать одно соединение на весь сеанс работы или создавать новое для каждого обмена. Однозначного ответа нет, выбор зависит от сценария.
Сравнение подходов
Проще и надежнее: объект умирает вместе с процедурой, нет риска удерживать зависшее соединение. Подходит для редких вызовов и регламентных заданий.
Экономит время на установке TCP и TLS-рукопожатия при частых запросах к одному серверу. Требует дисциплины: хранить объект в переменной модуля и обнулять при завершении работы.
При массовой отправке (тысячи запросов) пересоздавайте соединение порциями, например каждые несколько сотен запросов, чтобы сбрасывать накопленное состояние.
Для типовых задач — обмен с банком, отправка чеков, вызов REST API контрагента — рекомендуется создавать соединение локально внутри функции обмена. Это самый предсказуемый вариант: соединение гарантированно освобождается при выходе из функции, даже если разработчик забыл про обнуление.
Переиспользование оправдано при интенсивном обмене с одним сервером, когда накладные расходы на установку защищенного соединения заметны. В этом случае храните объект в переменной модуля и обязательно обнуляйте его при завершении сеанса обмена и при любой ошибке — после сбоя соединение может оказаться в неконсистентном состоянии.
Типичные проблемы и как их диагностировать
Если соединения не освобождаются, симптомы проявляются постепенно: растет потребление памяти рабочими процессами rphost, увеличивается число открытых сетевых подключений, регламентные задания обмена начинают завершаться с ошибками или зависать.
Проверьте, не хранятся ли HTTPСоединение в переменных модулей или в фоновых заданиях без обнуления
Убедитесь, что таймаут задан явно, а не используется значение по умолчанию
Проверьте наличие Попытка...Исключение и обнуления объекта в ветке ошибки
Сократите время жизни соединений, пересоздавайте объект порциями в циклах
Для диагностики полезно зафиксировать в журнале регистрации начало и конец каждого обмена с указанием длительности. Если между «началом» и «концом» систематически появляются записи без пары — код прерывается по исключению, и именно там теряется освобождение объекта.
На уровне операционной системы количество открытых подключений к конкретному серверу можно посмотреть стандартными средствами (например, netstat). Резкий рост числа соединений в состоянии ожидания — косвенный признак того, что объекты создаются чаще, чем освобождаются.
Особые сценарии: фоновые задания и длительные обмены
Обмен в фоновых и регламентных заданиях
В регламентных заданиях соединение живет до конца выполнения обработчика. Если задание зависло из-за отсутствия таймаута, соединение и сеанс удерживаются до принудительного завершения. Всегда задавайте таймаут и ограничивайте общую длительность обмена, а при проектировании закладывайте повторную попытку вместо бесконечного ожидания.
Загрузка и отправка больших файлов
Методы Получить и ОтправитьДляОбработки с записью в файл удерживают соединение все время передачи. Для больших файлов увеличьте таймаут пропорционально объему и убедитесь, что после завершения переменная обнуляется, а временные файлы удаляются — иначе к «зависшим» соединениям добавятся забитые каталоги временных файлов.
Прокси и аутентификация
Если обмен идет через прокси (объект ИнтернетПрокси), правила освобождения не меняются: прокси передается в конструктор и умирает вместе с соединением. Отдельно «закрывать» прокси не требуется.
Как проверить, что соединение действительно освобождено
Как проверить результат
Каждому событию начала обмена соответствует событие завершения
Есть начатые обмены без завершения — код прерывается по ошибке
После завершения обмена число соединений возвращается к исходному уровню
Соединения накапливаются и не закрываются со временем
После серии обменов потребление стабилизируется
Память растет монотонно от обмена к обмену
Обмен выполняется стабильно много раз подряд
Со временем появляются таймауты или ошибки подключения
Самый надежный тест — прогнать обмен в цикле несколько десятков раз на тестовой базе и наблюдать за памятью процесса и числом подключений. Стабильные показатели означают, что освобождение работает корректно.
Что важно запомнить
Метода Закрыть у HTTPСоединение нет: объект освобождается при потере ссылки. Создавайте соединение локально внутри функции, задавайте таймаут, оборачивайте обмен в Попытка...Исключение и обнуляйте переменную в обеих ветках. Контролируйте результат по журналу регистрации, памяти процессов и числу открытых подключений.
Частые вопросы
Почему у HTTPСоединение нет метода Закрыть или Close?
Архитектура платформы 1С основана на автоматическом управлении временем жизни объектов через подсчет ссылок. Освобождение ресурса происходит, когда на объект перестают ссылаться переменные. Поэтому вместо явного закрытия используется присваивание значения Неопределено или естественный выход переменной из области видимости.
Что будет, если вообще не освобождать соединение?
Если переменная локальная, объект уничтожится при выходе из процедуры автоматически. Проблемы возникают, когда ссылка хранится в переменной модуля, реквизите формы или общем модуле: тогда соединение живет до конца сеанса, удерживая сетевые ресурсы и память, а при массовом обмене такие объекты накапливаются.
Нужно ли закрывать HTTPЗапрос и HTTPОтвет отдельно?
Нет. Эти объекты также освобождаются сборщиком мусора при потере ссылок. Достаточно не хранить их без необходимости в долгоживущих переменных. Если ответ содержит большое тело, имеет смысл обработать его и обнулить переменную, чтобы быстрее освободить память.
Какой таймаут ставить для соединения?
Универсального значения нет: для быстрых API обычно достаточно десятков секунд, для передачи больших файлов таймаут увеличивают пропорционально объему и скорости канала. Главное правило — таймаут должен быть задан явно, чтобы зависший внешний сервис не блокировал сеанс 1С бесконечно.
Можно ли оборвать зависшее соединение без перезапуска сеанса?
Программно из кода 1С прервать уже выполняющийся синхронный вызов нельзя — он завершится по таймауту или по ответу сервера. Если сеанс завис полностью, его можно завершить через консоль кластера серверов 1С, но делать это следует осознанно: активные транзакции пользователя будут отменены.
Влияет ли защищенное соединение OpenSSL на освобождение ресурсов?
Объект ЗащищенноеСоединениеOpenSSL передается в конструктор и разделяет судьбу HTTPСоединение: отдельно закрывать его не нужно. Однако TLS-рукопожатие — самая затратная часть установки соединения, поэтому при частых запросах к одному серверу переиспользование объекта может быть оправдано.