Отправка данных¶
Отправка (в терминах подсистемы — «выгрузка») превращает зарегистрированные к обмену изменения информационной базы в сообщения Kafka. Что именно отправляется и в каком виде, решает обработчик обмена; подсистема отвечает за отбор данных, порядок, параллелизм, снятие регистрации и доставку.
Как проходит сеанс¶
Регламентное задание КафкаВыгрузка (или ручной запуск с формы шины)
└─ КафкаСервер.Выгрузить(Шина)
├─ ПередВыгрузкойШины ← обработчик может отменить сеанс
├─ выборка изменений по узлу плана обмена
├─ создание отправителя в шлюзе
├─ по каждому объекту метаданных в порядке обработчика:
│ ├─ ПередВыгрузкойТаблицы ← можно пропустить объект метаданных
│ ├─ нарезка на пакеты и раздача их потокам
│ └─ ПослеВыгрузкиТаблицы
├─ освобождение отправителя
└─ ПослеВыгрузкиШины ← вызывается и после ошибки
Сеанс выполняется в привилегированном режиме. Если по узлу нет ни одного зарегистрированного изменения, отправитель в шлюзе даже не создаётся — сеанс завершается сразу.
Отбор данных¶
Состав отправляемых данных определяется планом обмена: Узел шины указывает на узел, а его план обмена — на объекты метаданных, изменения которых регистрируются. Подсистема одним пакетным запросом забирает регистрацию по всем объектам метаданных состава: для ссылочных объектов — ссылки, для регистров — значения ключевых полей, для констант — признак наличия изменений.
Какие из этих объектов действительно отправлять и в каком порядке — решает обработчик, возвращая таблицу из метода ВыгружаемыеОбъектыМетаданных():
| Колонка | Смысл |
|---|---|
ПолноеИмя |
полное имя объекта метаданных, например Справочник.Номенклатура |
Порядок |
группа очерёдности |
РазмерПакета |
сколько объектов уходит в один пакет; если не задан — 250 |
Объекты метаданных обходятся в том порядке, в каком их вернул обработчик, поэтому строки нужно возвращать отсортированными по колонке Порядок. Метаданные, по которым нет зарегистрированных изменений, пропускаются без вызова событий.
Порядок — это барьер, а не просто сортировка
Перед тем как начать отправку данных нового значения Порядок, подсистема дожидается завершения всех потоков предыдущего. Это и есть механизм зависимостей: справочники в порядке 1, документы в порядке 2 — и ни один документ не уйдёт раньше, чем отправлены все справочники.
Пакеты и потоки¶
Данные объекта метаданных нарезаются на пакеты по РазмерПакета и раздаются в пул потоков, размер которого задан реквизитом шины «Количество потоков обмена».
- Один поток. Пакеты обрабатываются в текущем сеансе, без фоновых заданий. Дополнительно в конфигурацию отправителя добавляется
linger.ms=0— при последовательной отправке накапливать сообщения незачем. - Несколько потоков. Каждый пакет уходит в отдельное фоновое задание. Отправитель в шлюзе при этом один на всю шину: потоки работают с ним параллельно.
Если поток завершился аварийно или был отменён вручную, сеанс прерывается с ошибкой — остальные пакеты не отправляются, а их регистрация остаётся нетронутой.
Отправка одного объекта¶
Каждый объект обрабатывается в отдельной транзакции, внутри которой выполняется только необходимый минимум:
- разделяемая блокировка по ключевым полям объекта;
- чтение объекта — менеджер значения константы, объект по ссылке или набор записей регистра; если ссылочный объект уже удалён, вместо него формируется
УдалениеОбъекта; ПланыОбмена.УдалитьРегистрациюИзменений— снятие регистрации;ПередВыгрузкойОбъекта— обработчик может отказаться от отправки этого объекта;- формирование и отправка сообщения;
- фиксация транзакции.
После транзакции вызывается ПослеВыгрузкиОбъекта, которому передаётся 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), такое обращение не пройдёт — привяжите его к адресу, доступному внутри кластера, и ограничьте доступ сетевыми средствами.