跳到主要内容
版本:Next
schema_registryCODEC

Schema Registry

The schema_registry codec decodes Confluent wire-format messages by resolving the embedded schema id from a Confluent Schema Registry at runtime. Each schema version (id) is fetched at most once and cached per codec instance, so multi-version schema evolution is supported within the same stream. Both Protobuf and Avro subjects are supported, dispatched on the registry's schemaType response. An optional subject compatibility gate fails the stream fast when a subject's registered compatibility level drops below the configured minimum.

Configuration

FieldTypeRequiredDefaultDescription
typestringyesFixed value "schema_registry"
registry_urlstringyesConfluent Schema Registry root URL, e.g. http://localhost:8081
message_typestringconditionalFully qualified Protobuf message type. Required for Protobuf schemas; omit for Avro.
subjectstringnoRegistry subject for the compatibility gate.
min_compatibilitystringnonone, backward, forward or full (lowercase only; other values are rejected at config load). Minimum subject compatibility level enforced on the first decoded message. Requires subject.
authobjectnoRegistry authentication configuration
auth.typestringyes (if auth)Authentication method: basic or bearer
auth.usernamestringnoUsername for basic mode
auth.passwordstringnoPassword for basic mode
auth.tokenstringnoToken for bearer mode

Examples

Protobuf topic:

codec:
type: schema_registry
registry_url: http://localhost:8081
message_type: com.example.User

Avro topic with a compatibility gate:

codec:
type: schema_registry
registry_url: http://registry:8081
subject: orders-value
min_compatibility: backward

Bearer form:

codec:
type: schema_registry
registry_url: http://registry:8081
message_type: com.example.User
auth:
type: bearer
token: ${SR_TOKEN}

See examples/schema_registry.yaml and examples/schema_registry_avro.yaml.

Semantics

Wire format

[0x00 magic][4-byte big-endian schema id][payload]

The codec validates the magic byte, splits out the id and payload, then resolves the schema from the registry using the id.

Workflow

  1. Parse the Confluent wire format (magic + id + payload).
  2. Resolve the schema by id (GET {registry}/schemas/ids/{id}), caching it per id. The dispatch target comes from the response's schemaType:
    • PROTOBUF (also the default when the field is absent) → build a MessageDescriptor and decode the payload via the flat Protobuf→Arrow mapping.
    • AVRO → parse the Avro writer schema and decode the payload via the flat Avro→Arrow mapping.
  3. Merge the single-row batches of the request into one columnar batch.

Schema resolution is abstracted behind a pluggable SchemaResolver trait (RestSchemaResolver for production, an in-memory implementation for tests), so the wire format / caching / multi-version logic can be unit-tested without a real registry.

Avro → Arrow mapping

The flat mapping mirrors the Protobuf one: top-level record fields become columns. Supported types:

Avro typeArrow type
nullNull
booleanBoolean
intInt32
longInt64
floatFloat32
doubleFloat64
bytes, fixedBinary
string, enumUtf8
uuidUtf8
dateDate32
time-millis / time-microsTime32(ms) / Time64(µs)
timestamp-millis / timestamp-microsTimestamp(ms/µs, UTC)
local-timestamp-*Timestamp (no timezone)
decimalDecimal128 (precision ≤ 38)
["null", T] unionnullable T

Nested records, arrays, maps and unions with more than two branches are rejected with an explicit error rather than silently flattened.

Subject compatibility gate

With subject and min_compatibility configured, the first decoded message triggers a single GET {registry}/config/{subject}?defaultToGlobal=true request. The subject's registered level is ranked (NONE < BACKWARD/FORWARD incl. their _TRANSITIVE variants < FULL incl. FULL_TRANSITIVE); if it is below the configured minimum the stream fails with an error naming the subject, the actual level and the requirement. The verdict (pass or fail) is cached for the codec lifetime, so the config endpoint is hit at most once. This catches compatibility-policy degradation (e.g. a subject switched to NONE) at the pipeline instead of silently decoding incompatible future versions.

Notes / Non-goals

  • Decode-side only: it resolves schemas by id; it never registers new schemas, and encoding emits line-delimited JSON (registry-agnostic).
  • schemaType absent in the registry response is treated as PROTOBUF (ArkFlow convention kept for backward compatibility; note this differs from the Confluent API default of AVRO).
  • Debezium envelope flattening is not performed — payloads are mapped as their registered schema declares; nested envelope structs (source, before) are rejected by the flat mapping.
  • Protobuf schema references (imports) are not supported — only single-file schemas.
  • Avro decoding uses the writer schema only (no reader-schema resolution), matching the Protobuf path.
  • Local schema compatibility derivation (reader/writer schema resolution checks, POST /compatibility) is out of scope; the gate reads the registry's subject configuration, which is the compatibility authority.