Как реализовать асинхронную обработку запроса в HTTP-сервисе 1С, чтобы избежать таймаутов

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

При проектировании интеграций через HTTP-сервисы в 1С разработчики часто сталкиваются с ситуацией, когда входящий запрос инициирует выполнение тяжелого и длительного алгоритма. Это может быть формирование сложного отчета, серия запросов к внешним API или объемная обработка данных. Если выполнять такой код синхронно внутри процедуры-обработчика запроса, клиент (внешняя система) будет ждать ответа слишком долго, что неизбежно приведет к ошибке таймаута на стороне веб-сервера (IIS/Apache) или самого клиента.

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

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

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

Для реализации этого подхода выполним следующие шаги. Во-первых, вынесем тяжелый алгоритм в процедуру общего модуля, которая имеет флаг Сервер. Во-вторых, в коде HTTP-сервиса заменим прямой вызов функции на запуск фонового задания.

Посмотрим на пример кода:


Функция APIGET(Запрос)
    
    // Подготавливаем параметры для обработки
    ПараметрыЗадания = Новый Структура;
    ПараметрыЗадания.Вставить("ДанныеЗапроса", Запрос.ПолучитьТелоКакСтроку());
    
    // Запускаем асинхронное выполнение
    ФоновыеЗадания.Выполнить("МойОбщийМодуль.ДлинныйИспоняемыйКод", ПараметрыЗадания);
    
    // Мгновенно возвращаем ответ клиенту
    Ответ = Новый HTTPСервисОтвет(202); // Используем статус 202 (Принято)
    Возврат Ответ;
    
КонецФункции

Обратим внимание на важный нюанс: при создании фонового задания через ФоновыеЗадания.Выполнить, 1С создает новый сеанс. Выясним причину, почему это важно: фоновое задание не будет иметь доступа к параметрам текущего сеанса или временным таблицам, созданным в основном потоке. Все данные, необходимые для работы ДлинныйИспоняемыйКод, должны быть упакованы в структуру и переданы в качестве параметров.

Метод 2: Модель со статусом и токеном (Polling)

Если внешней системе все же нужно узнать результат обработки или получить данные, нам потребуется более сложная схема. Рассмотрим алгоритм "Запрос — Токен — Проверка".

  1. Клиент отправляет данные в 1С.
  2. 1С создает уникальный идентификатор (GUID) и записывает его в базу (например, в регистр сведений "ОчередьЗадач") вместе с входными параметрами. Статус записи устанавливается в "Принято".
  3. 1С возвращает клиенту этот GUID (токен).
  4. Параллельно запускается процесс обработки (через фоновое задание или регламентное задание).
  5. Клиент с определенной периодичностью обращается ко второму методу сервиса, передавая токен, чтобы проверить, готов ли результат.

Проанализируем пример кода для инициации такого процесса:


Функция PostData(Запрос)
    
    НовоеЗаданиеИД = Строка(Новый УникальныйИдентификатор());
    
    // Записываем задачу в регистр для отслеживания статуса
    МенеджерЗаписи = РегистрыСведений.СтатусыОбработкиЗапросов.СоздатьМенеджерЗаписи();
    МенеджерЗаписи.ИдентификаторЗадания = НовоеЗаданиеИД;
    МенеджерЗаписи.Статус = Перечисления.СтатусыЗадач.ВРаботе;
    МенеджерЗаписи.ДатаРегистрации = ТекущаяДата();
    МенеджерЗаписи.Записать();
    
    // Запускаем обработку
    Параметры = Новый Массив;
    Параметры.Добавить(НовоеЗаданиеИД);
    Параметры.Добавить(Запрос.ПолучитьТелоКакСтроку());
    ФоновыеЗадания.Выполнить("МойОбщийМодуль.ОбработатьИЗаписатьРезультат", Параметры);
    
    // Возвращаем токен клиенту
    Ответ = Новый HTTPСервисОтвет(202);
    Ответ.УстановитьТелоИзСтроки(НовоеЗаданиеИД);
    Возврат Ответ;
    
КонецФункции

Для проверки готовности клиент вызывает другой метод:


Функция CheckStatus(Запрос)
    
    ИД = Запрос.ПараметрыURL.Получить("id");
    Результат = РегистрыСведений.СтатусыОбработкиЗапросов.СоздатьКлючЗаписи(Новый Структура("ИдентификаторЗадания", ИД));
    
    // Код чтения из регистра и возврата статуса или данных
    // ...
    
КонецФункции

Метод 3: Использование промежуточной очереди и регламентных заданий

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

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

С точки зрения HTTP-сервиса код будет максимально коротким: ЗаписатьВРегистр() и Возврат 202. Вся "магия" происходит внутри регламентного задания.

Правильная обработка HTTP-статусов

В процессе обсуждения часто упоминается возврат статуса 200. Однако, согласно стандартам HTTP, для асинхронных операций правильнее использовать статус 202 Accepted. Это явно сообщает вызывающей системе: "Твой запрос корректен, я его принял, но работа еще не закончена".

Рассмотрим также заголовки ответа. Хорошим тоном считается использование заголовка Location. В нем вы можете передать URL, по которому клиент сможет проверить статус своей задачи. Это делает ваш API понятным для внешних разработчиков.

Технические нюансы и "подводные камни"

Проанализируем важные аспекты, о которых нельзя забывать при реализации асинхронности в 1С:

Выясним, какой метод выбрать. Если задача разовая и простая — используйте ФоновыеЗадания. Если данных много и критична нагрузка — используйте очередь через регистр сведений и регламентное задание. Если требуется обратная связь с клиентом — внедряйте схему с токенами или обратными вызовами.

← На главную