Как организовать асинхронное обращение к веб-сервису в 1С, чтобы избежать зависания системы?

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

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

Способ 1. Использование фоновых заданий на стороне клиента

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

Для этого нам необходимо создать экспортную процедуру в общем модуле (обязательно с установленными флажками «Сервер» и «Вызов сервера»). В этой процедуре будет описана вся логика подключения к WSПрокси или HTTPСоединение.


// В общем модуле (например, ИнтеграцияСервер)
Процедура ВыполнитьОбменССервисом(ПараметрыЗапроса) Экспорт
    // Здесь создаем соединение и отправляем данные
    Попытка
        Определения = Новый WSОпределения(ПараметрыЗапроса.URL);
        Прокси = Новый WSПрокси(Определения, ПараметрыЗапроса.URI, "ИмяСервиса", "ИмяПорта");
        Результат = Прокси.ОтправитьДанные(ПараметрыЗапроса.Данные);
        // Обработка результата или запись в лог
    Исключение
        ЗаписатьЛогОшибки(ОписаниеОшибки());
    КонецПопытки;
КонецПроцедуры

Теперь из формы или программного кода мы вызываем эту процедуру не напрямую, а через менеджер фоновых заданий:


ПараметрыВызова = Новый Структура("URL, Данные", "http://myservice.com/wsdl", ТекущиеДанные);
МассивПараметров = Новый Массив;
МассивПараметров.Добавить(ПараметрыВызова);

ФоновыеЗадания.Выполнить("ИнтеграцияСервер.ВыполнитьОбменССервисом", МассивПараметров, , "Обмен с веб-сервисом");

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

Способ 2. Изменение логики самого веб-сервиса (Паттерн «Квитанция»)

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

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

После этого клиентская база может либо периодически «спрашивать» о готовности (метод Polling), либо ожидать, пока вторая база сама вызовет ответный веб-сервис в первой базе (метод Callback). Посмотрим на пример логики получения результата через опрос:


// На стороне клиента периодически вызываем легкий метод
СтатусЗадачи = Прокси.ПолучитьСтатус(ИдентификаторЗадачи);
Если СтатусЗадачи = "Готово" Тогда
    Результат = Прокси.ПолучитьРезультат(ИдентификаторЗадачи);
КонецЕсли;

Способ 3. Асинхронные методы платформы (начиная с 8.3.18)

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

Например, для HTTP-запросов используется объект HTTPСоединение и метод НачатьВыполнениеЗапроса. Процесс выглядит так:

  1. Создаем ОписаниеОповещения, указывающее на процедуру, которая будет выполнена после получения ответа.
  2. Вызываем асинхронный метод.
  3. Код после вызова продолжает выполняться сразу же, не дожидаясь ответа от сервера.

ОповещениеЗавершения = Новый ОписаниеОповещения("ОбработатьОтветСервера", ЭтотОбъект);
Соединение.НачатьВыполнениеЗапроса(ОповещениеЗавершения, Запрос);
// Здесь код выполняется СРАЗУ, интерфейс не блокируется

Важно помнить, что такие методы доступны преимущественно в управляемом приложении и требуют аккуратной работы с контекстом формы.

Способ 4. Работа через очередь сообщений (Message Broker)

Если ваша система является высоконагруженной, то прямое соединение (Point-to-Point) между базами через веб-сервисы может стать «узким горлышком». В таких случаях рассмотрим подробнее использование посредников, таких как RabbitMQ или Apache Kafka.

Схема работы меняется кардинально:

Это полностью исключает проблему «зависания» базы-отправителя при недоступности или медлительности базы-приемника.

Способ 5. Использование механизмов БСП (Длительные операции)

Если в вашей конфигурации используется Библиотека стандартных подсистем (БСП), проанализируем ситуацию с использованием модуля ДлительныеОперации. Это наиболее «цивилизованный» способ реализации асинхронности в экосистеме 1С.

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


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

Если РезультатЗапуска.Статус = "Выполняется" Тогда
    ИдентификаторЗадания = РезультатЗапуска.ИдентификаторЗадания;
    // Подключаем обработчик ожидания для проверки статуса
КонецЕсли;

Важные рекомендации по настройке соединений

Независимо от выбранного способа, обязательно следует обращать внимание на следующие технические параметры:

Подведем итог: для простых задач достаточно использования ФоновыеЗадания.Выполнить(). Если требуется сложная интеграция с гарантированной доставкой и высокой нагрузкой — смотрите в сторону очередей сообщений или паттерна «Квитанция». Использование асинхронных методов платформы и БСП сделает ваше решение более современным и устойчивым к сбоям.

← На главную