При разработке интеграций с внешними системами через HTTP-сервисы мы часто сталкиваемся с ситуацией, когда обработка входящего запроса требует значительного времени. Это может быть связано с выполнением сложных расчетов, записью большого объема данных, взаимодействием с другими подсистемами или длительными транзакциями. Если HTTP-сеанс затягивается, клиентское приложение, отправившее запрос, будет ожидать ответа, что может привести к тайм-аутам, ошибкам и ухудшению общего пользовательского опыта. Давайте вместе разберем, как эффективно решать эту проблему, используя возможности платформы 1С:Предприятие.
Основной и наиболее рекомендуемый подход к решению проблемы длительных HTTP-сеансов — это асинхронная обработка. Суть метода заключается в том, чтобы немедленно ответить на HTTP-запрос, подтвердив его получение, а фактическую обработку данных перенести в фоновый режим. Рассмотрим этот подход подробнее.
Немедленный ответ и идентификатор задачи:
Когда система 1С получает HTTP-запрос, мы не начинаем его немедленную обработку. Вместо этого мы выполняем следующие шаги:
Новый УникальныйИдентификатор()
200 OK, в теле которого передаем этот сгенерированный идентификатор. Таким образом, вызывающая сторона получает подтверждение о приеме запроса и номер задачи, по которому она сможет отслеживать статус обработки и получать результаты.Этот шаг позволяет клиенту не ждать завершения всей обработки и избежать тайм-аутов.
Запуск фонового задания:
После сохранения данных и отправки ответа мы инициируем фоновое задание. Фоновые задания в 1С:Предприятии позволяют выполнять длительные операции асинхронно, не блокируя основной HTTP-сеанс и не занимая интерактивный сеанс пользователя. Мы можем передать в фоновое задание наш уникальный идентификатор и, возможно, другие параметры, необходимые для обработки.
Для запуска фонового задания используем метод
ФоновыеЗадания.Выполнить()
ИдентификаторЗадания = ФоновыеЗадания.Выполнить(
"МодульСервиса.ОбработатьДлительныйЗапрос", // Имя экспортной процедуры/функции
ИмяМетодаСервиса, // Имя метода HTTP-сервиса
ПараметрыЗадания, // Структура параметров, включая ID
"Обработка входящего HTTP-запроса " + ИдентификаторЗадачи
);
В процедуре
МодульСервиса.ОбработатьДлительныйЗапрос
Хранение состояния и результатов обработки:
Для отслеживания статуса фонового задания и хранения его результатов нам потребуется специальный регистр сведений. Давайте назовем его, например, ХранилищеXMLЗапросов или ОчередьОбработкиHTTP. В этом регистре мы будем хранить:
Когда фоновое задание завершается (успешно или с ошибкой), оно обновляет соответствующую запись в этом регистре сведений, указывая статус и результат. Клиент, имея ID задачи, может периодически обращаться к другому, более легковесному HTTP-сервису (например, /status/{ID}), чтобы узнать текущее состояние задачи и получить окончательный результат.
Надежность фоновых заданий:
Хотя фоновые задания и не имеют сохраняемого состояния в прямом смысле, для каждого задания создается системный сеанс, и они позволяют распараллеливать вычисления по рабочим процессам кластера. Однако важно понимать, что фоновые задания не гарантируют запись объектов в случае аварийного завершения работы службы сервера 1С (например, при обновлении платформы). Если выполнение фонового задания прервалось до завершения транзакции записи, данные могут быть потеряны. Именно поэтому мы сначала сохраняем исходные данные и только потом запускаем фоновое задание.
Теперь давайте разберем, как лучше всего хранить входящие данные, которые мы получили от клиента, до того, как их обработает фоновое задание. Это критически важный аспект для обеспечения надежности и производительности.
Регистр сведений как очередь:
Мы уже упомянули регистр сведений для отслеживания статуса. Этот же регистр будет служить и нашей "очередью" для входящих запросов. В нем мы будем хранить сами данные, которые нужно обработать.
Выбор типа реквизита для данных:
Возникает вопрос: в какой реквизит регистра сведений лучше записывать входящие данные (например, XML или JSON)?
ХранилищеЗначения. Этот тип данных предназначен для хранения произвольных двоичных или сериализованных данных, включая строки, объекты, файлы. Его ключевые преимущества:
ХранилищеЗначения поддерживает сжатие, что существенно уменьшает объем хранимой информации и экономит место в базе данных.ХранилищеЗначения, обычно выносятся в отдельные таблицы базы данных, что позволяет избегать замедления при чтении основных полей регистра.Для записи данных в ХранилищеЗначения вы можете использовать следующий подход:
ЗаписьРегистра = РегистрыСведений.ХранилищеXML.СоздатьМенеджерЗаписи();
ЗаписьРегистра.Период = ТекущаяДата();
ЗаписьРегистра.ID = УникальныйИдентификаторЗадачи;
ЗаписьРегистра.XML = Новый ХранилищеЗначения(Запрос.ПолучитьТелоКакСтроку(), Истина); // Истина = сжать
ЗаписьРегистра.Статус = "В очереди";
ЗаписьРегистра.Записать();
Параллельное хранение "живых" файлов:
В некоторых случаях, особенно если входящие данные представляют собой полноценные файлы или очень большие объемы информации, имеет смысл рассмотреть параллельное сохранение этих файлов в отдельный каталог на диске. Это дает дополнительный уровень надежности:
Далее, регламентное задание может периодически просматривать этот каталог и загружать документы из него, если они еще не были обработаны.
Автоматическая очистка старых данных:
Регистр сведений, используемый как очередь, будет постоянно расти. Для поддержания производительности и предотвращения разрастания базы данных критически важно настроить регулярную очистку устаревших записей. Мы рекомендуем хранить записи в течение определенного периода (например, 7-14 дней) для возможности анализа инцидентов, а затем удалять их.
Вот пример кода, который вы можете использовать для очистки регистра сведений (например, в регламентном задании):
ЗапросОчисткаРС = Новый Запрос;
ЗапросОчисткаРС.Текст =
"ВЫБРАТЬ
| ХранилищеXML.Период КАК Период,
| ХранилищеXML.ID КАК ID,
| ХранилищеXML.XML КАК XML,
| ХранилищеXML.НачалиОбрабатывать КАК НачалиОбрабатывать,
| ХранилищеXML.ДатаВремяНачалаОбработки КАК ДатаВремяНачалаОбработки,
| ХранилищеXML.УспешноОбработано КАК УспешноОбработано,
| ХранилищеXML.ОбщаяСумма КАК ОбщаяСумма,
| ХранилищеXML.Комментарий КАК Комментарий
|ИЗ
| РегистрСведений.ХранилищеXML КАК ХранилищеXML
|ГДЕ
| ХранилищеXML.Период < &Период";
// Удаляем записи старше 14 дней
ЗапросОчисткаРС.УстановитьПараметр("Период", ТекущаяДата() - 60*60*24*14);
РезультатЗапроса = ЗапросОчисткаРС.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Запись = РегистрыСведений.ХранилищеXML.СоздатьМенеджерЗаписи();
ЗаполнитьЗначенияСвойств(Запись, ВыборкаДетальныеЗаписи);
Запись.Прочитать(); // Прочитаем запись, чтобы получить ключевые поля
Запись.Удалить();
КонецЦикла;
Важно: убедитесь, что в запросе для удаления выбираются только ключевые поля регистра, чтобы метод Запись.Прочитать() работал корректно и находил нужную запись для удаления.
Помимо основных подходов, давайте рассмотрим ряд дополнительных рекомендаций, которые помогут нам сделать наши HTTP-сервисы более надежными, производительными и отказоустойчивыми.
Асинхронные методы платформы 1С (начиная с версии 8.3.18):
В современных версиях платформы 1С появились новые возможности для работы с асинхронными функциями, включая тип Обещание (Promise) и конструкции Асинх/Async и Ждать/Await. Эти механизмы позволяют организовать неблокирующее выполнение кода, когда основной поток продолжает работу, пока асинхронная функция выполняется "в фоне". Это повышает производительность и отзывчивость приложений, позволяя продолжить выполнение основной программы, пока запрос обрабатывается. Хотя для HTTP-сервисов чаще используются фоновые задания, понимание этих паттернов полезно для общего развития.
Использование внешних обработчиков/микросервисов:
Для особо ресурсоемких или длительных задач, которые могут сильно нагружать сервер 1С, мы можем рассмотреть интеграцию с внешними системами или микросервисами. Эти внешние компоненты будут обрабатывать часть запросов, разгружая основной сервер 1С. Это особенно полезно для задач, требующих больших вычислительных ресурсов, нетипичных для 1С (например, сложная обработка изображений, машинное обучение).
Мониторинг и управление фоновыми заданиями:
Крайне важно настроить мониторинг выполнения фоновых заданий. Мы должны отслеживать их статус, анализировать ошибки и иметь возможность управлять ими (отменять, блокировать) через стандартные средства 1С (например, через форму "Регламентные и фоновые задания") или собственную подсистему мониторинга. Это позволит оперативно реагировать на проблемы.
Оптимизация хранения больших данных:
При использовании ХранилищаЗначения для очень больших объемов информации (например, изображений, двоичных данных) мы рекомендуем создавать отдельные структуры данных (справочники или регистры сведений) для их хранения, а не помещать эти поля непосредственно в основные объекты. Это помогает избежать замедления работы системы, так как объекты считываются целиком.
В будущих версиях платформы 1С (например, 8.3.23) ожидается появление нового механизма "хранилища двоичных данных", предназначенного для хранения больших двоичных объектов (BLOB) вне основной базы данных. Это поможет решить проблемы с ростом объема базы, бэкапом, масштабированием и производительностью при работе с большими файлами. Мы будем внимательно следить за развитием этой возможности.
Переиспользование сеансов (с версии 8.3.9):
С версии 8.3.9 в 1С реализовано переиспользование сеансов, что позволяет нескольким пользователям или HTTP-запросам работать через один сеанс. Это снижает нагрузку на сервер и повышает общую производительность системы. Мы должны убедиться, что наша конфигурация настроена для использования этой возможности.
Оптимизация SQL-запросов:
Не забываем о базовых принципах оптимизации. Оптимизация SQL-запросов и использование индексов в базе данных способствуют более быстрой обработке запросов, что позволяет обрабатывать большее количество запросов одновременно. Профилирование и анализ запросов — наши лучшие друзья в этом вопросе.
Идемпотентность HTTP-запросов:
Для операций, которые могут повторяться (например, при сетевых сбоях или повторных отправках клиента), важно, чтобы повторный вызов не приводил к нежелательным побочным эффектам. Это называется идемпотентностью. Методы HTTP, такие как GET, HEAD, PUT и DELETE, по своей сути идемпотентны, тогда как POST — нет. Если наш HTTP-сервис обрабатывает POST-запросы, которые должны быть идемпотентными (например, создание уникального документа), мы должны реализовать логику проверки на дубликаты, используя, например, уникальный идентификатор запроса от клиента.
Снижение объема передаваемых данных:
Избыточные или неструктурированные ответы API увеличивают время сериализации, передачи и парсинга на стороне клиента. Мы должны стремиться к тому, чтобы возвращать только необходимые данные. Сокращение объема возвращаемых данных может существенно улучшить скорость работы HTTP-сервисов.
Применяя эти подходы, мы сможем создать надежные, производительные и отказоустойчивые HTTP-сервисы в 1С:Предприятии, которые смогут эффективно обрабатывать длительные запросы, не блокируя работу системы и обеспечивая отличный пользовательский опыт.
← К списку