В практике разработки интеграций на платформе 1С:Предприятие часто возникают ситуации, когда отлаженный и стабильно работающий код внезапно начинает вести себя непредсказуемо. Одной из наиболее распространенных и неприятных проблем является "зависание" выполнения кода при отправке HTTP-запросов к внешним API.
Рассмотрим типичный сценарий: у нас есть код, который успешно работал месяцами, но внезапно на строке получения ответа от сервера программа перестает реагировать, не выдавая ошибок сразу, а просто ожидая чего-то бесконечно долго. Давайте разберем, почему это происходит и как правильно модернизировать код, чтобы избежать подобных блокировок.
Обычно код выглядит стандартным образом. Мы создаем соединение, формируем запрос и пытаемся получить ответ. Проблема локализуется в строке вызова метода Получить().
// Пример проблемного кода
Соединение = Новый HTTPСоединение("api.example.com", , , , , , Новый ЗащищенноеСоединениеOpenSSL());
Запрос = Новый HTTPЗапрос("/v1/data");
Попытка
// Именно здесь происходит зависание
Ответ = Соединение.Получить(Запрос);
Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;
Если интернет-соединение стабильно, а сервер на той стороне (по словам их техподдержки) работает штатно, причина часто кроется в механизме ожидания ответа платформой 1С.
Самым эффективным и быстрым способом устранения "вечного" зависания является явное указание таймаута при создании объекта HTTPСоединение. По умолчанию, если таймаут не задан, платформа может ожидать ответа очень долго (в зависимости от настроек ОС и версии платформы), что и выглядит для пользователя как зависание сеанса.
В методе HTTPСоединение.Получить() нет параметра, отвечающего за время ожидания. Этот параметр задается на этапе инициализации соединения.
Давайте посмотрим на синтаксис конструктора и внесем необходимые изменения:
// Синтаксис конструктора
Новый HTTPСоединение(
<Сервер>,
<Порт>,
<Пользователь>,
<Пароль>,
<Прокси>,
<Таймаут>, // <--- Нам нужен этот параметр (6-й по счету)
<ЗащищенноеСоединение>,
<ИспользоватьАутентификациюОС>
)
Теперь применим это к нашему исходному коду. Рекомендуется устанавливать разумное время ожидания, например, 30 или 60 секунд, в зависимости от того, насколько "тяжелые" данные вы запрашиваете.
// Исправленный код с таймаутом (например, 30 секунд)
ТаймаутСек = 30;
Защита = Новый ЗащищенноеСоединениеOpenSSL();
// Передаем таймаут шестым параметром
Соединение = Новый HTTPСоединение("api.example.com",,,,, ТаймаутСек, Защита);
Запрос = Новый HTTPЗапрос("/v1/data");
Попытка
Ответ = Соединение.Получить(Запрос);
Если Ответ.КодСостояния <> 200 Тогда
Сообщить("Ошибка API: " + Ответ.КодСостояния);
КонецЕсли;
Исключение
// Теперь, если сервер не ответит за 30 секунд, мы попадем сюда
// с ошибкой "Превышено время ожидания"
Сообщить("Не удалось получить данные: " + ОписаниеОшибки());
КонецПопытки;
Использование параметра Таймаут гарантирует, что ваш фоновый процесс или сеанс пользователя не "повиснет" намертво, а вернет управление с ошибкой по истечении заданного времени. Это позволяет корректно обработать ситуацию: записать ошибку в лог, попробовать повторить запрос позже или уведомить администратора.
Хотя установка таймаута решает проблему симптоматически (программа перестает висеть вечно), полезно понимать, почему вообще происходит задержка. Если таймауты срабатывают часто, необходимо копать глубже. Разберем основные факторы.
В приведенном примере используется ЗащищенноеСоединениеOpenSSL. Зависание часто происходит на этапе так называемого "рукопожатия" (handshake), когда клиент (1С) и сервер договариваются о шифровании.
Сетевая инфраструктура также может быть источником проблем:
Если вы создаете объект HTTPСоединение в цикле (например, при выгрузке тысяч заказов по одному), могут закончиться свободные эфемерные порты в операционной системе.
Рекомендация: Старайтесь создавать один экземпляр HTTPСоединение и использовать его для отправки множества запросов через методы Получить() или ОтправитьДляОбработки(), меняя только объект HTTPЗапрос. Это снизит нагрузку на ОС и ускорит обмен.
Иногда проблема кроется не в 1С и не в конечном сервере, а в том, что находится между ними:
Если даже с установленным таймаутом вы регулярно получаете ошибки превышения времени ожидания, выполните следующие действия:
curl или PowerShell). Это поможет исключить проблемы самой платформы.Подводя итог: всегда используйте параметр Таймаут в конструкторе HTTPСоединение. Это правило хорошего тона, которое убережет вашу систему от долгих блокировок при любых сетевых сбоях.