Почему зацикливается фоновое задание при обмене через Web-сервис и как настроить очистку регистрации изменений?

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

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

Анализ причины: почему данные передаются повторно?

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

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

  1. В коде Web-сервиса вообще не предусмотрена очистка регистрации.
  2. База 2 не возвращает в Базу 1 номер принятого сообщения (квитанцию).
  3. Происходит обрыв соединения по таймауту после передачи данных, но до момента выполнения кода по очистке регистрации.

Поиск и проверка узла плана обмена

Многие разработчики ошибочно полагают, что при обмене через Web-сервисы узлы плана обмена не используются. На самом деле, без узла невозможно эффективно отслеживать только измененные данные. Если стандартная обработка "Регистрация изменений для обмена данными" не показывает нужный узел, вероятно, он создается или ищется в коде программно по специфическому коду или наименованию.

Рассмотрим, как найти программный узел, который используется для регистрации. Выполним следующий фрагмент кода в консоли кода:


ВыборкаУзлов = ПланыОбмена.ВашПланОбмена.Выбрать();
Пока ВыборкаУзлов.Следующий() Цикл
    Если ВыборкаУзлов.Ссылка = ПланыОбмена.ВашПланОбмена.ЭтотУзел() Тогда
        Продолжить;
    КонецЕсли;
    Сообщить("Найден узел: " + ВыборкаУзлов.Наименование + " [Код: " + ВыборкаУзлов.Код + "]");
КонецЦикла;

Проанализируем результат. Если узлов нет, кроме "ЭтотУзел", значит, обмен работает неоптимально (возможно, через полную выборку данных), и его нужно переводить на механизм ПланыОбмена.

Реализация механизма квитирования (подтверждения)

Чтобы "вылечить" зацикливание, необходимо реализовать двухэтапный процесс или передачу номера сообщения. Разберем по шагам правильную логику взаимодействия через Web-сервис:

Шаг 1. Получение данных и номера сообщения в Базе 1

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


// Код в Базе 1 (Web-сервис)
УзелОбъекта = ПланыОбмена.СинхронизацияДанных.НайтиПоКоду("База2");
ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();
ЗаписьСообщения.НачатьЗапись(ЗаписьXML, УзелОбъекта);
// НомерСообщения теперь доступен в ЗаписьСообщения.НомерСообщения
// Далее идет выгрузка данных...
ЗаписьСообщения.ЗакончитьЗапись();

Шаг 2. Передача подтверждения из Базы 2

После того как База 2 успешно записала все штрихкоды, она должна вызвать второй метод Web-сервиса в Базе 1 (например, ПодтвердитьПрием) и передать туда номер сообщения, который она только что получила.


// Код в Базе 2 (Регламентное задание)
РезультатПриема = Прокси.ВыполнитьЗагрузкуДанных();
Если РезультатПриема.Успешно Тогда
    Прокси.ПодтвердитьПрием(РезультатПриема.НомерСообщения);
КонецЕсли;

Шаг 3. Очистка регистрации в Базе 1

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


// Код в Базе 1 (Метод подтверждения)
Процедура ПодтвердитьПрием(НомерСообщения)
    УзелОбъекта = ПланыОбмена.СинхронизацияДанных.НайтиПоКоду("База2");
    ПланыОбмена.УдалитьРегистрациюИзменений(УзелОбъекта, НомерСообщения);
КонецПроцедуры

Проблема больших пакетов и таймаутов

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

Посмотрим, как увеличить время ожидания в коде Базы 2 при создании WSПрокси:


Определения = Новый WSОпределения(URL_WSDL, Логин, Пароль);
Прокси = Новый WSПрокси(Определения, URI_ПространстваИмен, ИмяСервиса, ИмяПорта);
Прокси.Timeout = 600; // Устанавливаем таймаут 10 минут (600 секунд)

Также рекомендуем разбивать выгрузку на порции. Вместо того чтобы тянуть все 2000 штрихкодов за один раз, передавайте по 500 штук. Это гарантирует, что каждый пакет будет обработан в рамках допустимого времени сессии Web-сервера (IIS или Apache).

Как принудительно сбросить счетчики?

Если счетчики сообщений рассинхронизировались и обмен "встал", можно программно их обнулить или установить в нужное значение. Посмотрим на пример использования метода УстановитьНомерОтправленного:


УзелОбъекта = ПланыОбмена.СинхронизацияДанных.НайтиПоКоду("База2");
// Сбрасываем счетчики в 0, чтобы начать обмен "с чистого листа"
ПланыОбмена.УстановитьНомерОтправленного(УзелОбъекта, 0);
ПланыОбмена.УстановитьНомерПринятого(УзелОбъекта, 0);

После выполнения этого кода в Базе 1 и аналогичного сброса в Базе 2 (если там есть ответный узел), механизмы Плана обмена начнут нумерацию заново, что часто помогает при "непонятных" зацикливаниях.

Резюме для исправления проблемы

Подведем итог нашим действиям. Чтобы вылечить зацикливание при обмене штрихкодами, нам необходимо:

  1. Убедиться, что в Базе 1 используется конкретный Узел плана обмена, а не ЭтотУзел.
  2. Проверить, что после выгрузки данных вызывается УдалитьРегистрациюИзменений.
  3. Реализовать возврат номера сообщения из Базы 2 в Базу 1 после успешной записи.
  4. При больших объемах данных увеличить Timeout в настройках WSПрокси.
  5. Если ручная очистка не помогает, воспользоваться обработкой "Регистрация изменений для обмена данными", найти нужный узел и вручную удалить регистрацию по регистру "Штрих-коды", чтобы прервать текущий цикл.

Следуя этой методике, мы обеспечим стабильную работу обмена даже при значительном росте объема передаваемых данных.

← На главную