Перейти к содержанию

Отправка данных

Отправка (в терминах подсистемы — «выгрузка») превращает зарегистрированные к обмену изменения информационной базы в сообщения Kafka. Что именно отправляется и в каком виде, решает обработчик обмена; подсистема отвечает за отбор данных, порядок, параллелизм, снятие регистрации и доставку.

Как проходит сеанс

Регламентное задание КафкаВыгрузка (или ручной запуск с формы шины)
  └─ КафкаСервер.Выгрузить(Шина)
      ├─ ПередВыгрузкойШины                    ← обработчик может отменить сеанс
      ├─ выборка изменений по узлу плана обмена
      ├─ создание отправителя в шлюзе
      ├─ по каждому объекту метаданных в порядке обработчика:
      │    ├─ ПередВыгрузкойТаблицы            ← можно пропустить объект метаданных
      │    ├─ нарезка на пакеты и раздача их потокам
      │    └─ ПослеВыгрузкиТаблицы
      ├─ освобождение отправителя
      └─ ПослеВыгрузкиШины                     ← вызывается и после ошибки

Сеанс выполняется в привилегированном режиме. Если по узлу нет ни одного зарегистрированного изменения, отправитель в шлюзе даже не создаётся — сеанс завершается сразу.

Отбор данных

Состав отправляемых данных определяется планом обмена: Узел шины указывает на узел, а его план обмена — на объекты метаданных, изменения которых регистрируются. Подсистема одним пакетным запросом забирает регистрацию по всем объектам метаданных состава: для ссылочных объектов — ссылки, для регистров — значения ключевых полей, для констант — признак наличия изменений.

Какие из этих объектов действительно отправлять и в каком порядке — решает обработчик, возвращая таблицу из метода ВыгружаемыеОбъектыМетаданных():

Колонка Смысл
ПолноеИмя полное имя объекта метаданных, например Справочник.Номенклатура
Порядок группа очерёдности
РазмерПакета сколько объектов уходит в один пакет; если не задан — 250

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

Порядок — это барьер, а не просто сортировка

Перед тем как начать отправку данных нового значения Порядок, подсистема дожидается завершения всех потоков предыдущего. Это и есть механизм зависимостей: справочники в порядке 1, документы в порядке 2 — и ни один документ не уйдёт раньше, чем отправлены все справочники.

Пакеты и потоки

Данные объекта метаданных нарезаются на пакеты по РазмерПакета и раздаются в пул потоков, размер которого задан реквизитом шины «Количество потоков обмена».

  • Один поток. Пакеты обрабатываются в текущем сеансе, без фоновых заданий. Дополнительно в конфигурацию отправителя добавляется linger.ms=0 — при последовательной отправке накапливать сообщения незачем.
  • Несколько потоков. Каждый пакет уходит в отдельное фоновое задание. Отправитель в шлюзе при этом один на всю шину: потоки работают с ним параллельно.

Если поток завершился аварийно или был отменён вручную, сеанс прерывается с ошибкой — остальные пакеты не отправляются, а их регистрация остаётся нетронутой.

Отправка одного объекта

Каждый объект обрабатывается в отдельной транзакции, внутри которой выполняется только необходимый минимум:

  1. разделяемая блокировка по ключевым полям объекта;
  2. чтение объекта — менеджер значения константы, объект по ссылке или набор записей регистра; если ссылочный объект уже удалён, вместо него формируется УдалениеОбъекта;
  3. ПланыОбмена.УдалитьРегистрациюИзменений — снятие регистрации;
  4. ПередВыгрузкойОбъекта — обработчик может отказаться от отправки этого объекта;
  5. формирование и отправка сообщения;
  6. фиксация транзакции.

После транзакции вызывается ПослеВыгрузкиОбъекта, которому передаётся RecordMetadata — ответ Kafka о принятом сообщении:

Поле Значение
topic тема, в которую попало сообщение
partition раздел
offset смещение сообщения в разделе
timestamp отметка времени
serializedKeySize, serializedValueSize размеры сериализованных ключа и значения

Гарантия доставки — «хотя бы один раз»

Снятие регистрации и отправка выполняются в одной транзакции, но Kafka не участвует в транзакции 1С. Если сообщение уже отправлено, а транзакция откатилась, регистрация останется — и в следующем сеансе объект будет отправлен повторно. Приёмная сторона должна быть готова к дублям: обычно достаточно идемпотентной записи по ключу сообщения.

Ключ, значение и тема

Ключ и значение каждого сообщения формирует обработчик — методами СообщениеКлюч и СообщениеЗначение. Возвращённые значения сериализуются по сердесам шины; допустимые типы и поведение особых значений описаны в разделе Сериализация ключей и значений. Если метод вернул Неопределено, сеанс завершится ошибкой «Не определен ключ сообщения» или «Не определено значение сообщения».

Когда имя темы шины заканчивается на *, оно считается префиксом: для каждого объекта вызывается СообщениеСуффиксТемы, и результат дописывается к префиксу. Так одна шина может раскладывать сообщения по темам — например, по видам объектов. Незаполненный суффикс — ошибка.

Заголовки сообщения

Заголовки собираются послойно, каждый уровень получает собственную копию и не влияет на соседей:

ПередВыгрузкойШины      → общие заголовки сеанса
  └─ ПередВыгрузкойТаблицы  → заголовки объекта метаданных
       └─ ПередВыгрузкойОбъекта, СообщениеКлюч, СообщениеЗначение → заголовки сообщения

Значения заголовков — строки; Неопределено и Null передаются в Kafka как заголовок без значения.

Что попадает в журнал регистрации

По каждому объекту метаданных пишутся записи о начале и завершении отправки с количеством объектов — событие Обмен данными.Кафка.<наименование шины>, уровень «Примечание». Ошибки сеанса пишутся с подробным представлением; разбор типичных сообщений — в разделе Диагностика.

Многосерверный кластер 1С

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

Потоки отправки — обычные фоновые задания, и кластер серверов 1С может запустить их на другом рабочем сервере. Такой поток обращается не к своему шлюзу, а к шлюзу сервера родительского сеанса — иначе отправитель, созданный родительским сеансом, был бы неизвестен. Когда адрес шлюза в настройках кластера задан как localhost, 127.0.0.1 или не заполнен, подсистема подставляет вместо него имя нужного сервера, сохраняя указанный порт.

Порт шлюза должен быть доступен с соседних серверов

В многосерверном кластере 1С обращение к шлюзу может прийти с другого рабочего сервера. Если шлюз слушает только петлевой интерфейс (-Dhost=127.0.0.1), такое обращение не пройдёт — привяжите его к адресу, доступному внутри кластера, и ограничьте доступ сетевыми средствами.