Перейти к основному содержимому

Механизм обмена данными

Механизмы обмена данными — это набор средств, предназначенных для организации обмена данными между «Исполнителем» и:

  • другими приложениями «1С:Исполнителя»;
  • информационными базами «1С:Предприятия»;
  • иными внешними информационными системами.

Центром механизма обмена данными являются планы обмена. В одном проекте можно определить произвольное количество планов обмена. Элементами данных плана обмена являются узлы плана обмена, подобно тому как элементами данных справочника являются элементы справочника. Каждый из узлов плана обмена обозначает участника обмена данными по данному плану обмена. Один из узлов соответствует данной информационной базе, а остальные — другим участникам, с которыми данная информационная база может обмениваться данными:

В планах обмена можно выделить три значимые составляющие:

Для реализации механизма обмена изменениями в «1С:Исполнителе» предназначен элемент проекта План Обмена. Данный элемент позволяет описать:

  • элементы проекта, в которых будет осуществляться регистрация изменения в данных;
  • участников обмена.

Приложения, которые обмениваются изменениями данных, называются узлами плана обмена. Узлы добавляются администратором в конкретном приложении, аналогично добавлению элементов справочника.

Состав плана обмена (элементы проекта, в которых регистрируются изменения данных) распространяется на все узлы данного плана обмена. Если с разными узлами нужно обмениваться разным составом информации, то необходимо создавать несколько планов обмена, в которых следует объединить узлы, обменивающиеся одинаковым составом информации.

Планы обмена подходят для относительно редких обменов данными, например, с периодичностью переноса изменений 1 раз в 10 минут.

Инфраструктура сообщений

Данные переносятся с помощью сообщений. Сообщения передаются в рамках плана обмена от одного узла другому. Средства работы с сообщениями образуют инфраструктуру сообщений. Каждое сообщение:

  • относится к определенному плану обмена;
  • имеет определенный узел-отправитель и определенный узел-получатель.

Сообщение нельзя отправить неизвестному узлу и принять от неизвестного узла. Каждое сообщение имеет свой собственный целочисленный номер. С точки зрения инфраструктуры сообщений у узла существуют два свойства:

  • номер отправленного сообщения,
  • номер принятого сообщения.

Для узла, соответствующего текущему приложению, эти свойства смысла не имеют (база данных сама с собой данными не обменивается).

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

<v8msg:Message xmlns:v8msg="http://v8.1c.ru/messages">
<v8msg:Header>
<v8msg:ExchangePlan>УдаленныеСклады</v8msg:ExchangePlan>
<v8msg:To>Оптовый</v8msg:To>
<v8msg:From>ЦентрОфис</v8msg:From>
<v8msg:MessageNo>20</v8msg:MessageNo>
<v8msg:ReceivedNo>15</v8msg:ReceivedNo>
</v8msg:Header>
<v8msg:Body>
<!— Тело сообщения -->
</v8msg:Body>
</v8msg:Message>

Все сообщение находится внутри элемента XML с именем Message, относящимся к пространству имен http://v8.1c.ru/messages. Сообщение состоит из:

  • заголовка — Header;
  • тела сообщения — Body.

Они также относятся к пространству имен http://v8.1c.ru/messages.

Структура заголовка жестко задана. Информация заголовка представлена в нескольких элементах XML, вложенных в элемент Header. Все элементы, вложенные в элемент Header, относятся к пространству имен http://v8.1c.ru/messages.

  • Элемент с именем ExchangePlan содержит имя плана обмена, к которому относится сообщение. Имена планов обмена должны совпадать в системах, взаимодействующих через планы обмена.
  • Элемент с именем From содержит код узла-отправителя.
  • Элемент с именем To содержит код узла-получателя.
  • Элемент с именем MessageNo содержит номер данного сообщения. Номер сообщения является положительным целым числом и присваивается узлом-отправителем. Номер каждого последующего сообщения равен номеру предыдущего отправленного сообщения плюс 1.
  • Элемент с именем ReceivedNo содержит максимальный номер сообщения, которое узел-отправитель данного сообщения принял от узла-получателя данного сообщения. Данное значение включено в состав заголовка сообщения для подтверждения приема сообщений.

Тело сообщения содержится в элементе XML с именем Body, относящимся к пространству имен http://v8.1c.ru/messages. Данный элемент может иметь произвольное содержимое, определяемое прикладными потребностями. Инфраструктурой сообщений содержимое тела сообщения никак не регламентируется.

дополнительно

Если вы настраиваете обмен данными с информационными базами «1С:Предприятия», при формировании тела сообщения важно придерживаться формата XML-сериализации, который используется в механизмах обмена данными «1С:Предприятия».

Сообщение для отправки может быть создано следующим образом:

метод ЗаписатьСообщениеОбмена(КодУзлаПолучателя : Строка, ИмяФайла : Строка)
пер Узел = УдаленныеСклады.НайтиПоКоду(КодУзлаПолучателя)


пер ФайлСообщенияОбмена = новый Файл(ИмяФайла)
пер ЗаписьXml = новый ЗаписьXml(ФайлСообщенияОбмена.ОткрытьПотокЗаписи())
исп ОбработкаИсходящегоСообщения = УдаленныеСклады.СоздатьОбработкуИсходящегоСообщения(ЗаписьXml, Узел)

// Заполнение тела сообщения
для Данные из УдаленныеСклады.ВыбратьИзмененияВСообщение(Узел, НомерСообщения)
// Запись данных, делает разработчик проекта
ЗаписатьДанныеВСообщениеОбмена(ОбработкаИсходящегоСообщения, Данные)
;
;

В результате вызова метода СоздатьОбработкуИсходящегоСообщения() создается объект типа ОбработкаИсходящегоСообщенияОбмена, с помощью которого может быть произведена запись одного или нескольких сообщений обмена данными, а также вызывается начало записи этих сообщений. В качестве первого параметра метода передается объект типа ЗаписьXML, в качестве второго — ссылка на узел-получатель плана обмена.

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

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

Метод ЗаписатьДанныеВСообщениеОбмена() разработчику следует определить самостоятельно.

Завершить запись сообщения можно с помощью трех методов объекта ОбработкаИсходящегоСообщенияОбмена:

  • Завершить()

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

  • Отменить()

    Прерывает запись сообщения. Сообщение при этом считается неотправленным. Запись сообщения обмена может быть завершена либо обращением к методу Завершить(), либо обращением к методу Отменить().

  • Закрыть() (вызывается автоматически при выходе из области видимости)

    Выполняется метод Отменить(), если закрытие произошло из-за выброса исключения. В ином случае выполняется метод Завершить().

Для чтения записанного в файл сообщения обмена в базе узла-получателя может использоваться следующий фрагмент кода:

метод ПрочитатьXmlСообщениеОбмена(Отправитель: Склады.Ссылка, ПотокФайла: ПотокЧтения)
знч ЧтениеXml = новый ЧтениеXml(ПотокФайла)
исп ГрупповаяОперация.Начать(РежимЗагрузкиДанных = Истина)
исп ОбработкаВходящегоСообщенияОбмена = Склады.СоздатьОбработкуВходящегоСообщения(
ЧтениеXml,
ДопустимыйНомерСообщенияОбмена.Больший
)
знч ОтправительСсылка = ОбработкаВходящегоСообщенияОбмена.Отправитель как Склады.Ссылка
если ОтправительСсылка != Отправитель
выбросить новый ИсключениеНедопустимоеСостояние("Отправитель в сообщении отличается от отправителя каталога")
;
Склады.УдалитьРегистрациюИзмененийПоСообщению(ОтправительСсылка, ОбработкаВходящегоСообщенияОбмена.НомерПринятого)
пока ЧтениеXml.ВидУзла == ВидУзлаXml.НачалоЭлемента
ПрочитатьИзменениеДанных(ЧтениеXml, ОтправительСсылка)
;
;

При вызове метода СоздатьОбработкуВходящегоСообщения(ЧтениеXml) создается объект, с помощью которого может быть произведено чтение одного или нескольких сообщений обмена данными. При этом производится чтение заголовка сообщения обмена данными и проверяются содержащиеся в заголовке данные. Если какие-либо данные указаны неправильно (задан неизвестный план обмена, указан узел, не в ходящий в план обмена, номер сообщения не соответствует ожидаемому), вызывается исключение. В начале чтения сообщения устанавливается блокировка на запись базы данных, соответствующую узлу плана обмена, чтобы предотвратить на время чтения сообщения другие операции чтения и записи сообщений, относящихся к данному узлу, а также не допустить изменения данных узла.

Используя второй параметр ДопустимыйНомерСообщенияОбмена, можно установить вариант ожидаемого номера сообщения:

  • любой (фактически контроль номеров сообщения не производится);
  • больший (любой номер, больший чем максимальный номер принятого сообщения);
  • следующий (строго больший на единицу, чем предыдущий).

Следует обратить внимание на тот факт, что в приведенном фрагменте кода нет указания ни на используемый план обмена (их в конфигурации может быть несколько), ни на узел-отправитель. Данная информация получается из заголовка сообщения.

Завершить чтение сообщения можно с использованием трех методов:

  • Завершить()

    Вызывает попытку нормального завершения чтения сообщения. При этом проверяется нормальное завершение сообщения. Если обнаружен конец элемента XML, соответствующего телу сообщения, то в случае превышения номером сообщения максимального номера принятого сообщения, он помещается в реквизит НомерПринятого узла плана обмена. Блокировка записи узла плана обмена снимается и сообщение считается принятым.

  • Отменить()

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

  • Закрыть() (вызывается автоматически при выходе из области видимости)

    Выполняется метод Отменить(), если закрытие произошло из-за выброса исключения. В ином случае выполняется метод Завершить().

При вызове метода УдалитьРегистрациюИзмененийПоНомеру() из таблиц регистрации изменений объектов удаляются регистрации изменений, относящиеся к указанному узлу, с номером сообщения меньшим или равным значению переданного номера сообщения.

Метод ПрочитатьИзмененияИзСообщенияОбмена() разработчику следует определить самостоятельно.

Служба регистрации изменений

Служба регистрации изменений предназначена для регистрации изменений данных, производимых «Исполнителем», чтобы при обмене данными иметь возможность передавать не все данные, а только новые, измененные или удаленные. Эти элементы данных должны быть переданы в очередном сообщении тому или иному узлу, с которым производится обмен данными. При каждом изменении данных должно быть зарегистрировано, что имеются изменения и их предстоит передать во все узлы, с которыми поддерживается обмен этими данными. При получении подтверждения приема сообщения, в котором были отправлены изменения, записи регистрации изменений должны быть удалены.

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

Регистрация изменений может выполняться для следующих элементов проекта:

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

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

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

Подтверждение приема сообщений

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

  • Элемент с именем MessageNo, который содержит номер данного сообщения.
  • Элемент с именем ReceivedNo, который содержит максимальный номер сообщения, которое узел-отправитель данного сообщения принял от узла-получателя данного сообщения. Данное значение включено в состав заголовка сообщения для подтверждения приема сообщений.

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

  • Код — код узла обмена, который используется для идентификации узла в другом узле обмена.
  • Номер отправленного — номер последнего сообщения, которое было отправлено в соответствующий узел обмена (MessageNo).
  • Номер принятого — номер последнего сообщения, которое было принято соответствующим узлом обмена (ReceivedNo).
  • Этот узел — узел, соответствующий данному приложению. Соответственно, для данного узла значения полей Номер отправленного и Номер принятого всегда равняются нулю.

Кроме того, существует один стандартный, однако необязательный реквизит:

  • Наименование — наименование узла обмена.

Рассмотрим на примере, каким образом реализуется подтверждение приема сообщений. Есть два приложения: «Офис» и «Склад», которые обмениваются изменениями данных в рамках плана обмена Склады:

  1. «Офис» отправляет сообщение на «Склад» с номером 1. В этот момент в заголовок сообщения, помимо прочих, будут записаны следующие значения:

    • MessageNo: 1 — номер сообщения, которое «Офис» отправляет на «Склад»;

    • ReceivedNo: 0 — информации о том, что «Склад» принял какое-либо сообщение, пока нет. В приложении «Офис», в плане обмена для узла «Склад», изменится значение поля:

    • Номер отправленного: 01

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

    • MessageNo: 1 — номер сообщения, которое «Склад» отправляет в «Офис»;

    • ReceivedNo: 1 — номер последнего сообщения, которое «Склад» принял от приложения «Офис». В приложении «Склад», в плане обмена для узла «Офис», изменится значение поля:

    • Номер отправленного: 01

  3. «Офис» принимает сообщение от приложения «Склад» с номером 1. Из заголовка сообщения будет считан номер последнего полученного складом сообщения: ReceivedNo: 1, после чего в приложении «Офис» в плане обмена для узла «Склад» изменится значение полей:

    • Номер принятого: 01

    • Затем сообщение от приложения «Офис» будет отправлено на «Склад». В этот момент в заголовок сообщения, помимо прочих, будут записаны следующие значения:

    • MessageNo: 2 — номер сообщения, которое «Офис» отправляет на «Склад»;

    • ReceivedNo: 1 — номер последнего сообщения, которое «Офис» принял от приложения «Склад».

    • В приложении «Офис», в плане обмена для узла «Склад», изменится значение поля:

      • Номер отправленного: 12

  4. «Склад» принимает сообщение от приложения «Офис» с номером 2. Из заголовка сообщения будет считан номер последнего полученного офисом сообщения: ReceivedNo: 1, после чего в приложении «Склад» в плане обмена для узла «Офис» изменится значение полей:

    • Номер принятого: 01

    • Затем сообщение со склада будет отправлено в офис. В этот момент в заголовок сообщения, помимо прочих, будут записаны следующие значения:

      • MessageNo: 2 — номер сообщения, которое «Склад» отправляет в «Офис»;

      • ReceivedNo: 2 — номер последнего сообщения, которое «Склад» принял от приложения «Офис».

        В приложении «Склад», в плане обмена для узла «Офис», изменится значение поля:

    • Номер отправленного: 12

См. также