При оптимизации интеграционных процессов часто возникает необходимость разделить один общий обмен данными на несколько независимых потоков — например, для раздельной синхронизации нормативно-справочной информации и оперативных документов. Рассмотрим, как платформа 1С:Предприятие обрабатывает одновременные подключения к веб-сервису, какие риски могут возникнуть при параллельном запуске регламентных заданий и как правильно спроектировать надежную схему взаимодействия.
Выясним причину, почему независимые вызовы веб-сервиса могут выполняться одновременно. В архитектуре платформы 1С:Предприятие каждый входящий HTTP- или SOAP-запрос к опубликованному веб-сервису обрабатывается в контексте отдельного независимого сеанса. Это справедливо даже в том случае, если оба фоновых задания авторизуются под одной и той же учетной записью пользователя базы данных.
Для эффективного обслуживания запросов на веб-сервере используется пул сеансов, настройки которого задаются в файле публикации default.vrd через параметры poolSize (максимальный размер пула) и poolTimeout (время жизни неактивного сеанса). При поступлении параллельного запроса веб-сервер берет свободный сеанс из пула либо создает новый. Таким образом, на уровне исполняемого контекста потоки не перезаписывают память друг друга.
Несмотря на то, что программные контексты изолированы, одновременное выполнение двух регламентных заданий может столкнуться со следующими проблемами:
ПланыОбмена.УдалитьРегистрациюИзменений(), один из потоков будет ждать снятия блокировки другим, что может приводить к ошибкам таймаута.Разберем по шагам правила и архитектурные приемы, которые позволяют организовать бесперебойный параллельный обмен данными через веб-сервисы.
1. Разделение узлов плана обмена
Если потоки передают разные категории данных, создадим в конфигурации для каждого потока свой отдельный узел плана обмена. Это полностью устранит конкуренцию за регистрацию изменений и номера сообщений.
2. Увеличение таймаута на стороне клиента
При создании объекта WSПрокси в коде регламентного задания обязательно зададим явный таймаут ожидания ответа, чтобы кратковременная блокировка на стороне сервера-приемника не разрывала соединение.
Определение = Новый WSОпределения(АдресWSDL, Пользователь, Пароль);
Прокси = Новый WSПрокси(Определение, URIПространстваИмен, ИмяСервиса, ИмяТочкиПодключения);
Прокси.Пользователь = Пользователь;
Прокси.Пароль = Пароль;
Прокси.Таймаут = 120; // Увеличиваем таймаут ожидания ответа до 120 секунд
3. Использование механизма повторных попыток транзакций
Для устойчивости к случайным блокировкам обернем код обработки и записи пакета данных в цикл повторных попыток с обработкой исключительных ситуаций.
КоличествоПопыток = 3;
Успешно = Ложь;
Для НомерПопытки = 1 По КоличествоПопыток Цикл
НачатьТранзакцию();
Попытка
// Выполняем запись полученных данных
ЗаписатьДанныеОбмена(ПакетДанных);
ЗафиксироватьТранзакцию();
Успешно = Истина;
Прервать;
Исключение
ОтменитьТранзакцию();
ИнформацияОбОшибке = ОписаниеОшибки();
Если НомерПопытки = КоличествоПопыток Тогда
ЗаписьЖурналаРегистрации("ОбменДанными", УровеньЖурналаРегистрации.Ошибка,,,
"Не удалось записать данные после " + КоличествоПопыток + " попыток: " + ИнформацияОбОшибке);
ВызватьИсключение;
КонецЕсли;
// Кратковременная пауза перед повторной попыткой
Приостановить(1);
КонецПопытки;
КонецЦикла;
4. Применение асинхронной очереди сообщений
Если объем передаваемых данных велик, наиболее надежным архитектурным решением является разделение процесса на транспорт и обработку. Веб-сервис принимает пакет и моментально сохраняет его в служебный регистр сведений (очередь входящих пакетов) без проведения документов. Последующую распаковку, проверку и проведение выполняет отдельное регламентное задание в фоновом режиме по очереди.