Learning Platform
Глоссарий Troubleshooting
Урок 07.01 · 20 мин
Средний
Schema ManagementSchema EvolutionContractSchema Registry

Зачем управлять схемами

Представьте команду, которая развивает сервис заказов. Продюсер отправляет события в топик orders. Три команды-потребителя — аналитики, финансы, склад — читают эти события и строят на них свою бизнес-логику. В один прекрасный день команда продюсера решает добавить новое поле и переименовать старое. Деплой без координации. Через минуту у трёх команд падают десериализация, стекстрейсы в мониторинге и пейджинг на дежурного.

Это и есть проблема schema evolution в production Kafka.


Мир без Schema Registry

Без централизованного управления схемами каждая команда решает проблему сериализации по-своему. Вот типичные антипаттерны:

Неявный контракт через документацию. Схема сообщения описана в Confluence или README. Команда продюсера меняет формат — обновляет документ. Потребители узнают об этом через инциденты, не через систему.

Хардкодинг формата. Consumer ожидает ровно те поля, что были в первой версии схемы. При добавлении нового поля — код не ломается, но игнорирует данные. При переименовании — NullPointerException в рантайме.

Версионирование через имена топиков. orders-v1, orders-v2, orders-v3. Каждый breaking change требует создания нового топика, миграции потребителей, параллельного чтения двух топиков в переходный период. Экспоненциальный операционный рост.

Отсутствие ранней проверки. Продюсер генерирует сообщение в неправильном формате. Ошибка обнаруживается только когда Consumer пытается десериализовать — спустя секунды или минуты после отправки. Debugging по логам на стороне потребителя.

WARNING

Без Schema Registry нет механизма, который предотвратил бы публикацию несовместимой схемы в топик. Это означает, что сломанный формат может попасть в топик, обработаться продюсером как успех, а потом сломать потребителей — которые никак не участвовали в решении о смене формата.


Схема как контракт

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

Контракт работает в обе стороны:

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

Ключевой принцип: эволюция контролируется, а не запрещается. Schema Registry не блокирует изменения схемы — он проверяет их на совместимость с предыдущими версиями согласно выбранному режиму (BACKWARD, FORWARD, FULL или NONE, подробно — в Уроке 04).


Как работает Schema Registry

Schema Registry — это отдельный HTTP-сервис, работающий рядом с Kafka-кластером. Он хранит схемы в subjects — именованных группах версий одной схемы. При регистрации новой версии проверяется совместимость с существующими.

Алгоритм работы при публикации сообщения:

  1. Продюсер регистрирует схему (или переиспользует существующую). Schema Registry возвращает целочисленный schema_id.
  2. Продюсер сериализует данные используя библиотеку (KafkaAvroSerializer, KafkaProtobufSerializer и т.д.), которая формирует wire format: магический байт + 4-байтный schema_id + сериализованные данные. Подробно о wire format — в Уроке 02.
  3. Kafka хранит байты без какого-либо знания о схеме — брокер видит только непрозрачный payload.
  4. Потребитель читает сообщение и извлекает schema_id из wire format (первые 5 байт).
  5. Потребитель запрашивает схему у Schema Registry по schema_id. Schema Registry кэшируется на стороне потребителя — повторных HTTP-запросов для одного и того же ID нет.
  6. Десериализация выполняется с использованием полученной схемы.
Schema Registry: Поток регистрации и чтения схемы
Producer регистрирует схему, Consumer получает её по schema ID из wire format

Producer

Producer: сериализует данные в Avro/Protobuf/JSON Schema. Перед отправкой регистрирует схему в Schema Registry (или получает существующий ID).
register schema / get ID

Schema Registry

Schema Registry: хранит схемы по subject. Возвращает schema_id при регистрации. Проверяет совместимость при добавлении новой версии.

Producer

Producer формирует wire format: 0x00 + schema_id (4 байта) + serialized payload. Отправляет в Kafka.
[0x00][schema_id][payload]

Kafka Topic

Kafka Broker: хранит сырые байты. Не знает о схеме — wire format для брокера непрозрачен. Брокер не участвует в сериализации.
consume

Consumer

Consumer: читает сообщение, извлекает первые 5 байт wire format. Получает schema_id из байт 1-4.

Consumer

Consumer запрашивает Schema Registry по schema_id. Результат кэшируется — HTTP-запрос только при первой встрече с данным ID.
GET /schemas/ids/{id}

Schema Registry

Schema Registry возвращает схему по ID. Consumer использует схему для десериализации payload.

Архитектура Schema Registry

Schema Registry — это stateless HTTP-сервис (Confluent реализация написана на Java). Состояние хранится в Kafka: все зарегистрированные схемы записываются в специальный топик _schemas (compacted, внутренний). Это означает:

  • Schema Registry перезапускаем без потери данных — при старте восстанавливает состояние из _schemas.
  • Schema Registry масштабируется горизонтально — несколько инстансов образуют кластер; запись идёт через leader, чтение — с любого инстанса.
  • Зависимость от Kafka — Schema Registry требует работающего Kafka-кластера. В docker-compose Schema Registry стартует после Kafka.

Порт по умолчанию: 8081. REST API принимает и возвращает JSON. Пример регистрации схемы:

POST /subjects/orders-value/versions
Content-Type: application/vnd.schemaregistry.v1+json

{"schema": "{\"type\":\"record\",\"name\":\"Order\",...}", "schemaType": "AVRO"}

Интеграция с экосистемой Kafka

Schema Registry встраивается во все компоненты Kafka-экосистемы:

Producers используют KafkaAvroSerializer (или Protobuf/JSON Schema аналог). Сериализатор автоматически регистрирует схему при первой отправке.

Consumers используют KafkaAvroDeserializer. Десериализатор автоматически запрашивает схему по ID из wire format.

Kafka Connect использует AvroConverter (или ProtobufConverter, JsonSchemaConverter) на уровне воркера или отдельного коннектора. AvroConverter работает через Schema Registry — каждый Source connector регистрирует схему производимых записей, каждый Sink connector читает схему при потреблении. Подробно о AvroConverter в Kafka Connect — в Модуле 05, Урок 01.

Kafka Streams поддерживает Avro через SpecificAvroSerde и GenericAvroSerde. Схемы SerDe регистрируются автоматически.


Три поддерживаемых формата

Schema Registry поддерживает три формата сериализации:

  • Avro — бинарный формат, наиболее распространённый в Kafka-экосистеме, первоклассная поддержка Schema Registry. Рекомендован по умолчанию.
  • Protobuf — Protocol Buffers, бинарный формат от Google. Предпочтителен для gRPC-heavy микросервисов.
  • JSON Schema — человекочитаемый JSON. Простой в отладке, но медленнее и без строгих гарантий совместимости.

Подробное сравнение форматов — в Уроке 03.


Альтернативы Confluent Schema Registry

В курсе мы используем именно Confluent Schema Registry (CSR) как референс — это наиболее распространённая реализация, и большинство клиентских библиотек (KafkaAvroSerializer, AvroConverter в Kafka Connect) изначально написаны под её API. Однако в современной экосистеме существует несколько альтернатив, и выбор не всегда тривиален:

  • Apicurio Registry — open-source проект Red Hat под лицензией Apache 2.0. Совместим с Confluent SR API на уровне REST-эндпоинтов (есть compatibility-слой), поддерживает несколько backend’ов хранения: Kafka, PostgreSQL, MS SQL Server. Помимо Avro/Protobuf/JSON Schema умеет хранить OpenAPI и AsyncAPI-спецификации — удобно если у команды единый registry для контрактов всей экосистемы.
  • AWS Glue Schema Registry — fully-managed AWS-сервис, нативная интеграция с MSK, Kinesis, Lambda. Естественный выбор для команд all-in на AWS. Тесно интегрирован с IAM для авторизации.
  • Buf Schema Registry (BSR) — реестр от Buf специально для Protobuf-схем. Удобен для команд, у которых Kafka — лишь один из транспортов Protobuf-сообщений (gRPC, Connect, REST → Protobuf). Версионирование через Git-подобные модули.
  • Karapace — open-source 1-к-1 drop-in replacement для CSR от Aiven, Apache 2.0, написан на Python. API совместим с CSR — клиентские библиотеки работают без изменений. Появился в 2020 году именно как ответ на лицензионные изменения Confluent.
WARNING

Confluent Schema Registry распространяется под Confluent Community License — это несвободная (non-FOSS) лицензия, запрещающая, в частности, предоставление SR как managed-сервиса другими провайдерами. Для open-source проектов и команд, чувствительных к license-compliance, это блокер. Apicurio Registry и Karapace — основные Apache 2.0 альтернативы с тем же REST API, что у CSR.

В остальных уроках модуля мы будем говорить о Schema Registry в общем смысле — концепции (subjects, compatibility-modes, wire format) применимы ко всем перечисленным реализациям, отличаются лишь нюансы API и операционной поддержки.


NOTE

Если вы прошли курс Debezium, вы видели Schema Registry в CDC-контексте: Debezium использует SR для схем событий change capture с envelope-форматом (before/after поля). В этом модуле мы рассматриваем Schema Registry как самостоятельный слой контрактного управления, применимый к любой паре producer-consumer.

Проверка знанийKnowledge check
Продюсер пытается отправить сообщение, используя схему, которая не зарегистрирована в Schema Registry и не совместима с текущей версией subject. Что произойдёт?
ОтветAnswer
Сериализатор (KafkaAvroSerializer) вернёт исключение на стороне продюсера ещё до отправки сообщения в Kafka. Регистрация/валидация схемы происходит при сериализации — если Schema Registry отклоняет схему (несовместимость) или сериализатор не может зарегистрировать новую схему (ошибка соединения, нет прав), сообщение не попадёт в топик. Это ключевое отличие от мира без Schema Registry: ошибка обнаруживается на стороне продюсера, а не потребителя.

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 4. Продюсер отправил сообщение в топик orders, используя схему, которую он попытался зарегистрировать в Schema Registry, но получил HTTP 409 Conflict. Какое действие предпримет KafkaAvroSerializer в этом случае?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 6