При проектировании интеграций через HTTP-сервисы в 1С разработчики часто сталкиваются с ситуацией, когда входящий запрос инициирует выполнение тяжелого и длительного алгоритма. Это может быть формирование сложного отчета, серия запросов к внешним API или объемная обработка данных. Если выполнять такой код синхронно внутри процедуры-обработчика запроса, клиент (внешняя система) будет ждать ответа слишком долго, что неизбежно приведет к ошибке таймаута на стороне веб-сервера (IIS/Apache) или самого клиента.
Разберем детально, как изменить логику работы сервиса таким образом, чтобы 1С мгновенно подтверждала получение запроса, а основную работу выполняла "за кулисами". Проанализируем несколько подходов: от простых фоновых заданий до сложных систем с очередями и обратными вызовами.
Рассмотрим наиболее прямолинейное решение: запуск длительного кода в фоновом задании. Этот метод идеально подходит в ситуациях, когда вызывающей стороне не важен результат обработки, а нужно лишь подтверждение, что 1С приняла данные на вход (например, при реализации веб-хуков).
Для реализации этого подхода выполним следующие шаги. Во-первых, вынесем тяжелый алгоритм в процедуру общего модуля, которая имеет флаг Сервер. Во-вторых, в коде HTTP-сервиса заменим прямой вызов функции на запуск фонового задания.
Посмотрим на пример кода:
Функция APIGET(Запрос)
// Подготавливаем параметры для обработки
ПараметрыЗадания = Новый Структура;
ПараметрыЗадания.Вставить("ДанныеЗапроса", Запрос.ПолучитьТелоКакСтроку());
// Запускаем асинхронное выполнение
ФоновыеЗадания.Выполнить("МойОбщийМодуль.ДлинныйИспоняемыйКод", ПараметрыЗадания);
// Мгновенно возвращаем ответ клиенту
Ответ = Новый HTTPСервисОтвет(202); // Используем статус 202 (Принято)
Возврат Ответ;
КонецФункции
Обратим внимание на важный нюанс: при создании фонового задания через ФоновыеЗадания.Выполнить, 1С создает новый сеанс. Выясним причину, почему это важно: фоновое задание не будет иметь доступа к параметрам текущего сеанса или временным таблицам, созданным в основном потоке. Все данные, необходимые для работы ДлинныйИспоняемыйКод, должны быть упакованы в структуру и переданы в качестве параметров.
Если внешней системе все же нужно узнать результат обработки или получить данные, нам потребуется более сложная схема. Рассмотрим алгоритм "Запрос — Токен — Проверка".
Проанализируем пример кода для инициации такого процесса:
Функция PostData(Запрос)
НовоеЗаданиеИД = Строка(Новый УникальныйИдентификатор());
// Записываем задачу в регистр для отслеживания статуса
МенеджерЗаписи = РегистрыСведений.СтатусыОбработкиЗапросов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.ИдентификаторЗадания = НовоеЗаданиеИД;
МенеджерЗаписи.Статус = Перечисления.СтатусыЗадач.ВРаботе;
МенеджерЗаписи.ДатаРегистрации = ТекущаяДата();
МенеджерЗаписи.Записать();
// Запускаем обработку
Параметры = Новый Массив;
Параметры.Добавить(НовоеЗаданиеИД);
Параметры.Добавить(Запрос.ПолучитьТелоКакСтроку());
ФоновыеЗадания.Выполнить("МойОбщийМодуль.ОбработатьИЗаписатьРезультат", Параметры);
// Возвращаем токен клиенту
Ответ = Новый HTTPСервисОтвет(202);
Ответ.УстановитьТелоИзСтроки(НовоеЗаданиеИД);
Возврат Ответ;
КонецФункции
Для проверки готовности клиент вызывает другой метод:
Функция CheckStatus(Запрос)
ИД = Запрос.ПараметрыURL.Получить("id");
Результат = РегистрыСведений.СтатусыОбработкиЗапросов.СоздатьКлючЗаписи(Новый Структура("ИдентификаторЗадания", ИД));
// Код чтения из регистра и возврата статуса или данных
// ...
КонецФункции
В высоконагруженных системах создание фонового задания на каждый чих может привести к перегрузке сервера (исчерпанию лимита сеансов). Разберем ситуацию, когда запросов много, и нам нужно контролировать нагрузку. В этом случае вместо мгновенного запуска фонового задания мы просто пишем данные в таблицу очереди.
Выясним преимущества такого подхода: стабильность и гарантия доставки. Даже если сервер 1С будет перезагружен, записи в регистре никуда не денутся. Специальное регламентное задание, работающее по расписанию (например, раз в минуту), будет выбирать порции данных из этой очереди и обрабатывать их по порядку.
С точки зрения HTTP-сервиса код будет максимально коротким: ЗаписатьВРегистр() и Возврат 202. Вся "магия" происходит внутри регламентного задания.
В процессе обсуждения часто упоминается возврат статуса 200. Однако, согласно стандартам HTTP, для асинхронных операций правильнее использовать статус 202 Accepted. Это явно сообщает вызывающей системе: "Твой запрос корректен, я его принял, но работа еще не закончена".
Рассмотрим также заголовки ответа. Хорошим тоном считается использование заголовка Location. В нем вы можете передать URL, по которому клиент сможет проверить статус своей задачи. Это делает ваш API понятным для внешних разработчиков.
Проанализируем важные аспекты, о которых нельзя забывать при реализации асинхронности в 1С:
ConnectionTimeout и RequestTimeout в конфигурационных файлах вашего веб-сервера (web.config для IIS или httpd.conf для Apache). Но помним, что асинхронность — более надежный путь.Выясним, какой метод выбрать. Если задача разовая и простая — используйте ФоновыеЗадания. Если данных много и критична нагрузка — используйте очередь через регистр сведений и регламентное задание. Если требуется обратная связь с клиентом — внедряйте схему с токенами или обратными вызовами.