Как в 1С отправить HTTP-запрос без ожидания ответа (асинхронно)

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

В процессе разработки интеграций в 1С часто возникает ситуация, когда необходимо инициировать отправку данных во внешнюю систему, но при этом не блокировать выполнение основного кода или работу пользователя. По умолчанию стандартный объект 1С HTTPСоединение работает синхронно: программа отправляет запрос и «замирает», ожидая ответа от сервера. Если сервер долго обрабатывает данные, работа в 1С приостанавливается. Рассмотрим подробнее, как реализовать принцип «выстрелил и забыл» (fire and forget) в среде 1С.

Решение 1: Использование фоновых заданий (рекомендуемый способ)

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

Разберем по шагам, как это реализовать. Сначала создадим процедуру в общем модуле (модуль должен иметь флаг «Сервер» и «Вызов сервера» или быть глобальным серверным модулем):


// Общий модуль: ИнтеграцияВызовСервера
Процедура ОтправитьЗапросФоновымЗаданием(ПараметрыЗапроса) Экспорт
    
    Попытка
        Соединение = Новый HTTPСоединение(ПараметрыЗапроса.АдресСервера);
        Запрос = Новый HTTPЗапрос(ПараметрыЗапроса.Ресурс);
        Запрос.УстановитьТелоИзСтроки(ПараметрыЗапроса.Данные);
        
        // Здесь выполнение остановится до получения ответа, 
        // но это не заблокирует основной поток пользователя
        Ответ = Соединение.ОтправитьДляОбработки(Запрос);
    Исключение
        // Логируем ошибку, так как пользователь ее не увидит
        ЗаписьЖурналаРегистрации("HTTP_Асинхрон", УровеньЖурналаРегистрации.Ошибка, , , ОписаниеОшибки());
    КонецПопытки;
    
КонецПроцедуры

Теперь проанализируем, как вызвать этот код из основной обработки или документа, не дожидаясь завершения:


ПараметрыВызова = Новый Структура;
ПараметрыВызова.Вставить("АдресСервера", "api.myserver.com");
ПараметрыВызова.Вставить("Ресурс", "/v1/data");
ПараметрыВызова.Вставить("Данные", "{'status': 'done'}");

// Запускаем фоновое задание и сразу идем дальше
ФоновыеЗадания.Выполнить("ИнтеграцияВызовСервера.ОтправитьЗапросФоновымЗаданием", ПараметрыВызова);

Важный нюанс: при использовании фоновых заданий следует помнить, что каждое такое задание расходует лицензию на сеанс (в некоторых версиях платформы). Если запросов сотни в минуту, лучше использовать очередь сообщений.

Решение 2: Использование системных команд (cURL)

Если нам нужно максимально абстрагироваться от ресурсов 1С и не занимать сеансы фоновыми заданиями, мы можем делегировать отправку запроса операционной системе. Для этого отлично подходит утилита cURL, которая предустановлена во многих дистрибутивах Linux и последних версиях Windows 10/11.

Проанализируем ситуацию: мы вызываем внешнее приложение, которое работает независимо от процесса 1cv8.exe. Для этого используем метод ЗапуститьПриложение. Рассмотрим пример для Windows:


Команда = "cmd /c start /b curl -X POST https://api.site.com/endpoint -d ""data=test""";
ЗапуститьПриложение(Команда, , Ложь); // Третий параметр Ложь означает "не ждать завершения"

В этом примере параметры означают следующее:

  1. cmd /c start /b — запускает консольную команду в фоновом режиме, не открывая нового окна.
  2. curl — сама утилита для HTTP-запроса.
  3. Ложь (в методе 1С) — основной поток 1С не будет ждать, пока cURL закончит свою работу.

Решение 3: COM-объект WinHTTP (только для Windows)

Для тонкой настройки асинхронности можно использовать COM-объект WinHttp.WinHttpRequest.5.1. Он поддерживает асинхронный режим работы на уровне самой библиотеки Windows.

Выясним, как настроить этот объект. В методе Open пятый параметр Async отвечает за асинхронность:


HttpЗапрос = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");
// Параметры: Метод, URL, Асинхронно (True)
HttpЗапрос.Open("POST", "http://example.com/api", Истина);
HttpЗапрос.SetRequestHeader("Content-Type", "application/json");

// Запрос улетает, и управление сразу возвращается в 1С
HttpЗапрос.Send("{'key': 'value'}"); 

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

Решение 4: Установка минимальных таймаутов (Грязный хак)

Существует специфический подход, когда мы намеренно ограничиваем время ожидания ответа до минимума. Рассмотрим ситуацию, когда нам важно только то, чтобы сервер «увидел» начало передачи данных.


// Устанавливаем таймаут в 1-2 секунды
Соединение = Новый HTTPСоединение("myserver.com", , , , , 1); 
Запрос = Новый HTTPЗапрос("/fast-api");

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

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

Архитектурные рекомендации по асинхронности

При реализации асинхронных запросов важно учитывать следующие моменты:

  1. Гарантия доставки: Если данные критически важны (например, передача заказа в службу доставки), «выстрелил и забыл» — плохая стратегия. В таких случаях лучше использовать Очередь заданий или внешние брокеры сообщений (RabbitMQ, Kafka). 1С записывает задачу в таблицу «Очередь», а отдельное регламентное задание с определенной периодичностью пытается отправить эти данные, помечая их как «Отправлено» только при получении кода 200 OK.
  2. Логирование: Поскольку ответа в основном потоке нет, обязательно записывайте результаты выполнения (успех/ошибка) в Журнал Регистрации или специальный регистр сведений.
  3. Нагрузка: Массовый запуск фоновых заданий может «положить» рабочий сервер 1С. Всегда ограничивайте количество одновременно работающих потоков.

Подведем итог: если вам нужно быстрое и «штатное» решение внутри 1С — используйте ФоновыеЗадания. Если вы хотите сэкономить ресурсы сервера 1С и работаете под Windows — используйте cURL через ЗапуститьПриложение.

← На главную