К статье
Практический материал

Администрирование · 10 мин

Как разорвать HTTP-соединение в 1С: практическое руководство

Как принудительно разорвать HTTP-соединение в 1С: прерывание по таймауту, закрытие объекта HTTPСоединение, обработка ошибок и типичные ошибки при обмене с веб-сервисами.

HTTP-соединение в 1С создаётся через объект HTTPСоединение и используется при обмене данными с веб-сервисами, API, сайтами и облачными сервисами. Проблема в том, что встроенный язык 1С не предоставляет метода Закрыть() для этого объекта — соединение закрывается автоматически при уничтожении переменной или по завершении вызова. Поэтому «разорвать соединение» на практике означает: ограничить время ожидания таймаутом, корректно обработать ошибки и гарантировать, что зависший запрос не заблокирует сеанс пользователя или фоновое задание навсегда.

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

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

Объект HTTPСоединение создаётся конструктором Новый HTTPСоединение(Сервер, Порт, ...) и живёт, пока существует переменная, в которую он помещён. Платформа управляет сокетом сама: физическое TCP-соединение открывается при первом вызове Получить(), ОтправитьДляОбработки() и подобных методов, а закрывается при уничтожении объекта сборщиком мусора или по таймауту на стороне сервера.

Из этого следует главное практическое правило: чтобы «разорвать» соединение, нужно либо дождаться таймаута, либо освободить объект, присвоив переменной Неопределено. Однако если запрос уже отправлен и платформа ждёт ответа, присваивание Неопределено не прервёт ожидание — код продолжит стоять на строке вызова, пока не сработает таймаут или сервер не ответит.

Способ 1. Задать таймаут при создании соединения

Основной и единственно надёжный способ не допустить бесконечного ожидания — указать таймаут в конструкторе. Четвёртый параметр Новый HTTPСоединение() задаёт время ожидания в секундах. Если сервер не ответит за это время, платформа разорвёт соединение и выбросит исключение, которое можно обработать в блоке Попытка...Исключение.

Типичный безопасный шаблон выглядит так:

Попытка

Соединение = Новый HTTPСоединение("api.example.ru", 443, , , , 30,

Новый ЗащищенноеСоединениеOpenSSL);

Запрос = Новый HTTPЗапрос("/v1/data");

Ответ = Соединение.Получить(Запрос);

Если Ответ.КодСостояния = 200 Тогда

Результат = Ответ.ПолучитьТелоКакСтроку();

КонецЕсли;

Исключение

ЗаписьЖурналаРегистрации("Обмен.HTTP", УровеньЖурналаРегистрации.Ошибка, , ,

ОписаниеОшибки());

КонецПопытки;

Соединение = Неопределено;

Значение таймаута подбирайте под задачу: для быстрых API достаточно 15–30 секунд, для загрузки больших файлов — 300–600 секунд. Никогда не оставляйте таймаут равным 0 в регламентных заданиях: одно зависание остановит весь обмен.

Способ 2. Освободить объект и прервать цепочку запросов

Если соединение используется для серии запросов и нужно разорвать его между ними, присвойте переменной значение Неопределено. Платформа освободит объект, и TCP-соединение будет закрыто. Это полезно, когда после ошибки требуется гарантированно новое соединение, а не переиспользование старого.

Учтите ограничение: прервать уже выполняющийся синхронный вызов Получить() из того же кода невозможно — встроенный язык 1С однопоточен в рамках вызова. Прерывание возможно только извне: через завершение фонового задания или сеанса.

Порядок действий при зависшем запросе
  1. 1
    Убедитесь, что в коде задан таймаут у HTTPСоединение
  2. 2
    Дождитесь срабатывания таймаута и зафиксируйте ошибку в журнале регистрации
  3. 3
    Если таймаут не задан — завершите фоновое задание или сеанс принудительно
  4. 4
    Добавьте в код обработку исключений и освобождение переменной соединения
  5. 5
    Повторите обмен и проверьте, что запрос завершается управляемо

Способ 3. Завершить фоновое задание или сеанс принудительно

Когда зависший HTTP-запрос выполняется в фоновом задании, разорвать его можно извне. В клиент-серверном варианте откройте консоль кластера серверов 1С, найдите сеанс фонового задания в списке сеансов и выполните команду «Завершить сеанс». Соединение разорвётся вместе с завершением процесса-обработчика.

Программно фоновое задание отменяется методом ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ИД).Отменить(). Метод Отменить() запрашивает прерывание: если код в этот момент находится в ожидании HTTP-ответа, задание завершится с ошибкой при срабатывании прерывания или таймаута. В файловом варианте без сервера 1С остаётся только закрытие сеанса пользователя или процесса.

Для массовых случаев зависания проверьте также настройки прокси и брандмауэра: часто запрос «висит» не из-за 1С, а потому что сетевое оборудование молча отбрасывает пакеты, и TCP-стек ждёт ответа, который никогда не придёт.

Маршрут решения

Как выбрать действие

Запрос выполняется в интерактивном сеансе и интерфейс зависЗавершите сеанс через консоль кластера или дождитесь таймаута, затем добавьте таймаут в код
Зависло фоновое задание обменаНайдите задание по уникальному идентификатору и вызовите Отменить() или завершите сеанс в консоли
Зависания повторяются регулярноСократите таймаут, добавьте повторные попытки с задержкой и логирование в журнал регистрации
Сервер доступен, но ответы приходят медленноУвеличьте таймаут до разумного предела и перенесите обмен в фоновое задание

Способ 4. Настройки на уровне сервера и инфраструктуры

Помимо кода, разрывом соединений управляют внешние компоненты. Веб-сервер (IIS, Apache) при публикации HTTP-сервисов 1С имеет собственные таймауты: если клиент молчит дольше заданного времени, веб-сервер сам закроет соединение. При публикации HTTP-сервисов сверяйте таймауты веб-сервера с ожидаемой длительностью обработки запросов.

Если 1С работает через прокси, параметры прокси задаются объектом ИнтернетПрокси и передаются в конструктор соединения. Неверно настроенный прокси — типичная причина «вечного» ожидания: проверьте, что запрос вообще доходит до целевого сервера, например, выполнив аналогичный запрос из браузера или утилитой curl с того же сервера 1С.

bsl
Прокси = Новый ИнтернетПрокси(Истина);
Прокси.Установить("http", "proxy.local", 8080, "user", "pass");
Соединение = Новый HTTPСоединение("api.example.ru", 443, , , Прокси, 60,
    Новый ЗащищенноеСоединениеOpenSSL);

Обработка ошибок и повторные попытки

Разрыв соединения по таймауту — это всегда исключительная ситуация, и её нужно обрабатывать явно. Минимальный набор: блок Попытка...Исключение, запись ошибки в журнал регистрации и освобождение переменной соединения. Без записи в журнал диагностика повторяющихся сбоев превращается в гадание.

Для обменов, критичных к надёжности, реализуйте повторные попытки с нарастающей паузой: например, три попытки с задержками 10, 30 и 60 секунд. Каждая попытка должна создавать новое соединение — переиспользовать объект после ошибки не рекомендуется, так как его внутреннее состояние после обрыва не гарантировано.

Типичные ошибки
01
Таймаут 0 в конструкторе — запрос может ждать бесконечно и блокировать сеанс
02
Повторное использование объекта HTTPСоединение после ошибки — непредсказуемое поведение следующего запроса
03
HTTP-вызов внутри транзакции записи — зависший запрос удерживает блокировки в базе
04
Игнорирование кода состояния ответа — тело ошибки обрабатывается как корректные данные
05
Отсутствие записи ошибок в журнал регистрации — причина сбоев остаётся неизвестной

Как проверить, что соединение действительно разорвано

После завершения обмена убедитесь, что не осталось «висящих» соединений. На сервере 1С это видно в консоли кластера: у завершившегося сеанса не должно быть активных вызовов. На уровне операционной системы список TCP-соединений рабочего процесса смотрят командой netstat -ano (Windows) или ss -tp (Linux) — соединения в состоянии ESTABLISHED к целевому серверу после завершения обмена говорят об утечке.

В коде контроль простой: после блока обмена переменная соединения должна быть равна Неопределено, а в журнале регистрации — запись об успешном завершении или об ошибке с понятным текстом. Отсутствие записи о завершении при наличии записи о старте — признак того, что запрос завис или сеанс был убит принудительно.

Контрольные точки

Как проверить результат

Журнал регистрации после обмена
Норма

Есть запись об успешном завершении или обработанной ошибке

Тревожный признак

Запись о старте есть, записи о завершении нет — запрос завис или сеанс убит

Сетевые соединения процесса rphost/ragent
Норма

Нет ESTABLISHED-соединений к внешнему API после завершения обмена

Тревожный признак

Соединения накапливаются и не закрываются

Поведение при недоступном сервере
Норма

Исключение по таймауту за заданное время, запись в журнал

Тревожный признак

Сеанс висит бесконечно, таймаут не срабатывает

Итог

Что важно запомнить

Явного метода закрытия у HTTPСоединение нет: управляйте разрывом через таймаут в конструкторе, освобождайте переменную после работы, обрабатывайте исключения и логируйте ошибки. Зависшие запросы устраняйте отменой фонового задания или завершением сеанса, а причину повторных зависаний ищите в сетевой инфраструктуре.

Частые вопросы

Есть ли в 1С метод Закрыть() у HTTPСоединения?

Нет. Соединение закрывается автоматически при уничтожении объекта. Чтобы освободить его вручную, присвойте переменной значение Неопределено. Прервать уже выполняющийся синхронный запрос из того же кода нельзя — только через таймаут или внешнее завершение задания.

Что произойдёт, если не указать таймаут?

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

Как прервать зависший обмен, не перезапуская сервер 1С?

Откройте консоль кластера серверов, найдите нужный сеанс в списке и завершите его. Перезапуск всего сервера не требуется — затрагивается только зависший сеанс. Для фоновых заданий альтернатива — программный вызов метода Отменить().

Можно ли выполнять HTTP-запросы асинхронно, чтобы не блокировать интерфейс?

Да. Вынесите обмен в фоновое задание через ДлительныеОперации (БСП) или ФоновыеЗадания.Выполнить(). Клиент получит управление сразу, а результат заберёт по завершении. Это стандартный подход для всех обменов дольше нескольких секунд.

Почему соединение рвётся раньше заданного таймаута?

Таймаут могут урезать промежуточные узлы: прокси, брандмауэр, балансировщик или веб-сервер перед API. Проверьте настройки таймаутов на всём пути запроса — самое маленькое значение в цепочке и будет фактическим пределом.

Нужно ли создавать новое соединение для каждого запроса?

Для одного логического обмена допустимо переиспользовать объект соединения — это быстрее. Но после любой ошибки или обрыва создавайте новый объект: состояние старого после исключения не гарантировано, и повторное использование может дать сбойный запрос.