Man mano che le tue applicazioni e i relativi requisiti dei dati cambiano, anche la struttura dei messaggi Kafka deve adattarsi. Una gestione efficace del ciclo di vita dello schema è fondamentale per gestire queste modifiche senza problemi e mantenere l'integrità dei dati. Questo processo non comporta solo la modifica degli schemi, ma anche il controllo sistematico dei tipi di modifiche sicure o sufficientemente compatibili per le applicazioni che dipendono da essi.
Il registro di schema Managed Service per Apache Kafka supporta l'intero ciclo di vita della gestione degli schemi e include le seguenti funzionalità:
Definisci e applica regole di compatibilità (tipo di compatibilità) per gestire l'evoluzione dello schema quando vengono introdotte nuove versioni dello schema. Queste regole garantiscono che produttori e consumatori continuino a operare correttamente.
Configura i controlli operativi (modalità schema) per gestire la modificabilità degli schemi a diversi livelli, salvaguardando le pipeline di elaborazione dei dati.
Gestisci i riferimenti allo schema per promuovere la riusabilità e la coerenza tra gli schemi.
Come funziona l'evoluzione dello schema
Modifichi la definizione dello schema. Ad esempio, aggiungi un campo facoltativo al tuo file
.protoo.avsc.Un produttore configurato con
auto.register.schemas=trueinvia un messaggio utilizzando il nuovo schema oppure tenti esplicitamente di registrare il nuovo schema utilizzando l'API o le librerie client.Quando una richiesta di registrazione per una nuova versione raggiunge il registro di schema, recupera la regola di compatibilità configurata per l'oggetto di destinazione. Confronta il nuovo schema proposto con le versioni precedenti richieste in base a questa regola.
Se la versione dello schema è compatibile, il nuovo schema viene registrato correttamente come versione successiva nell'oggetto, viene assegnato un nuovo numero di versione e, potenzialmente, un nuovo
schema_idse la definizione è univoca.Il produttore (se applicabile) riceve il
schema_idda includere nei messaggi.Se la versione dello schema non è compatibile, il tentativo di registrazione non riesce e viene restituito un errore.
Informazioni sul tipo di compatibilità
La compatibilità dello schema ti consente di definire in che modo il registro di schemi gestisce i controlli di compatibilità tra diverse versioni dello schema. Puoi applicare queste configurazioni a vari livelli all'interno della gerarchia del registro di schemi, come indicato dalle seguenti opzioni di pattern di risorse:
A livello di registro:imposta la configurazione predefinita per l'intero registro di schemi.
- Percorso:
projects/project/locations/location/schemaRegistries/schema_registry/config
- Percorso:
A livello di soggetto nel contesto predefinito:imposta una configurazione specifica per un soggetto all'interno del contesto predefinito del registro.
- Percorso:
projects/project/locations/location/schemaRegistries/schema_registry/config/subject
- Percorso:
A livello di soggetto in un contesto specifico: imposta una configurazione specifica per un soggetto all'interno di un contesto denominato.
- Percorso:
projects/project/locations/location/schemaRegistries/schema_registry/contexts/context/config/subject
- Percorso:
Le configurazioni impostate a livello di soggetto sostituiscono quelle impostate a livello di registro.
Se un'impostazione non è specificata a livello di soggetto, eredita il valore dal livello del registro. Se non è impostato esplicitamente a livello di registro,
il valore predefinito è Backward.
I seguenti tipi disponibili determinano il modo in cui il registro degli schemi confronta una nuova versione dello schema con quelle precedenti:
None: non vengono eseguiti controlli di compatibilità. Consente qualsiasi modifica, ma comporta un elevato rischio di interruzione dei client.Backward(impostazione predefinita): le applicazioni consumer che utilizzano il nuovo schema possono decodificare i dati prodotti solo con lo schema registrato in precedenza. Ciò consente di aggiungere campi facoltativi ed eliminare campi. I consumatori devono essere aggiornati prima dei produttori.Backward_transitive: le applicazioni consumer che utilizzano il nuovo schema possono decodificare i dati prodotti con tutte le versioni precedenti dello schema in questo argomento. Questa impostazione è più restrittiva diBackward.Forward: i dati prodotti utilizzando il nuovo schema devono essere leggibili dai client che utilizzano lo schema registrato precedente. I produttori devono essere aggiornati per primi, ma i consumatori che utilizzano il nuovo schema potrebbero non essere in grado di leggere i dati prodotti con schemi ancora più vecchi. Questa impostazione consente di eliminare i campi facoltativi e di aggiungerne altri.Forward_transitive: i dati prodotti utilizzando il nuovo schema devono essere leggibili utilizzando tutte le versioni precedenti dello schema. Questa impostazione è più restrittiva diForward.Full: il nuovo schema è compatibile sia con le versioni precedenti che con quelle successive della versione dello schema registrata in precedenza. I client possono essere aggiornati in qualsiasi ordine rispetto al produttore utilizzando il nuovo schema. Consente di aggiungere o eliminare campi facoltativi.Full_transitive: il nuovo schema è compatibile sia con le versioni precedenti che con quelle successive di tutti gli schemi precedenti nell'oggetto. Questa impostazione è più restrittiva diFull.
Esempio per il tipo di compatibilità
Supponiamo di avere un registro di schemi con il tipo di compatibilità Backward. Puoi anche
creare diversi soggetti all'interno di questo registro, che ereditano la compatibilità
Backward del registro.
Per un argomento specifico denominato user-events, sono necessarie
regole di compatibilità più rigorose. Aggiorni il livello di compatibilità dello schema per l'oggetto
user-events a Full.
In questa situazione, si applicano le seguenti regole:
Qualsiasi nuova versione dello schema registrata nell'oggetto
user-eventsdeve essere compatibile sia con le versioni precedenti che con quelle successive della versione dello schema registrata in precedenza per quell'oggetto.Gli altri soggetti nel registro degli schemi rispettano comunque l'impostazione di compatibilità
Backwarda livello di registro, a meno che la loro compatibilità non sia stata configurata in modo esplicito.
Se in un secondo momento modifichi il livello di compatibilità del registro di schemi in
Forward, questa modifica influirà sulla compatibilità predefinita di tutti i nuovi
soggetti creati all'interno del registro. Tuttavia, l'argomento user-events manterrà la compatibilità Full impostata in modo esplicito, poiché le configurazioni a livello di argomento sostituiscono quelle a livello di registro.
Questo dimostra come puoi avere un livello di compatibilità predefinito per l'intero registro, pur avendo la flessibilità di definire requisiti di compatibilità specifici per i singoli soggetti in base alle esigenze della tua applicazione.
Per saperne di più, consulta Aggiornare il tipo di compatibilità.
Best practice per la modalità di compatibilità
Non utilizzare
Nonecome strategia per il tipo di compatibilità perché rischi di interrompere i client con modifiche allo schema.Scegli una strategia basata sull'avanzamento, ad esempio
ForwardoForward-transitive, se vuoi aggiornare prima i produttori. Scegli una strategia basata sul passato, ad esempioBackwardoBackward-transitive, se vuoi aggiornare prima i consumatori.Scegli una strategia transitiva se vuoi mantenere la compatibilità con più versioni precedenti dello schema. Se vuoi massimizzare la compatibilità e ridurre al minimo il rischio di interruzione dei client durante l'aggiornamento delle versioni dello schema, utilizza la strategia
Full-transitive.
Informazioni sui riferimenti allo schema
I riferimenti allo schema ti consentono di definire strutture comuni
una sola volta e farvi riferimento da più schemi. Ad esempio, uno schema Address potrebbe essere utilizzato sia in uno schema Customer sia in uno schema Supplier.
Questo approccio promuove la riusabilità e la coerenza tra gli schemi. Inoltre, l'utilizzo di riferimenti allo schema crea dipendenze chiare, monitorando esplicitamente quali schemi si basano su altri. Ciò migliora la manutenibilità dell'architettura dello schema.
Quando uno schema deve utilizzare un altro schema comune, include un riferimento a
questo schema comune. Questa relazione è definita formalmente da una struttura SchemaReference.
Un SchemaReference è costituito dai seguenti componenti:
name(stringa): il nome completo dello schema a cui viene fatto riferimento per i formati Avro o il nome file di un tipo importato per i formati Protobuf, come utilizzato all'interno della definizione dello schema stesso.subject(stringa): il nome del soggetto in base al quale lo schema a cui viene fatto riferimento è registrato nel registro di schema.version(int32): il numero di versione specifico dello schema a cui viene fatto riferimento.
Uno schema che utilizza altri schemi dichiara queste dipendenze in un campo references. Questo campo contiene un elenco di oggetti SchemaReference.
Esempio per i riferimenti allo schema
Supponiamo che tu debba definire schemi sia per i dati Customer che per i dati Supplier
ed entrambi devono includere un indirizzo. Con i riferimenti allo schema, puoi definire la struttura dell'indirizzo una sola volta e riutilizzarla.
Per seguire questo esempio, consulta Crea un argomento.
Crea un soggetto denominato
address_schemae registra la definizione di un indirizzo standard. Quando crei un soggetto per la prima volta, crei anche la versione 1 dello schema per quel soggetto.Avro
Crea e memorizza questo file come versione 1 dell'argomento
address_schema_avro.{ "type": "record", "name": "Address", "namespace": "com.example.common", "fields": [ {"name": "street", "type": "string"}, {"name": "city", "type": "string"}, {"name": "zipCode", "type": "string"}, {"name": "country", "type": "string", "default": "USA"} ] }Protobuf
Crea e memorizza questo file come versione 1 dell'argomento
address_schema_proto.syntax = "proto3"; package com.example.common; message Address { string street = 1; string city = 2; string zip_code = 3; string country = 4; }Crea lo schema
customer_schema. Anziché ripetere i campi dell'indirizzo, fai riferimento allo schemaaddress_schema.Avro
Il tipo
com.example.common.Addressdel campobillingAddressfa riferimento allo schemaAddressdefinito nel passaggio precedente.{ "type": "record", "name": "Customer", "namespace": "com.example.crm", "fields": [ {"name": "customerId", "type": "long"}, {"name": "customerName", "type": "string"}, // This field's type refers to the Address schema {"name": "billingAddress", "type": "com.example.common.Address"} ] }Quando registri
customer_schema_avro, i relativi metadati includono un riferimento allo schema:// Conceptual metadata for customer_schema_avro "references": [ { "name": "com.example.common.Address", "subject": "address_schema_avro", "version": 1 } ]Protobuf
Il file
customer.protoimportaaddress.protoe utilizzacom.example.common.Addressper il campobilling_address.syntax = "proto3"; package com.example.crm; import "address.proto"; message Customer { int64 customer_id = 1; string customer_name = 2; // This field's type refers to the imported Address message com.example.common.Address billing_address = 3; }Quando registri
customer_schema_proto, i relativi metadati includono un riferimento allo schema:// Conceptual metadata for customer_schema_proto "references": [ { "name": "address.proto", "subject": "address_schema_proto", "version": 1 } ]Allo stesso modo, per lo schema
Supplier, aggiungeresti un riferimento allo schema che punta allo stesso schemaAddresscomune.
Informazioni sulla modalità schema
La modalità dello schema definisce lo stato operativo di un registro di schemi o di un argomento specifico e controlla i tipi di modifiche consentite. La modalità dello schema può essere applicata a un registro o a un argomento specifico all'interno di un registro di schemi. Di seguito sono riportati i percorsi per le risorse della modalità Schema:
Modalità a livello di registro:si applica all'intero registro degli schemi.
- Percorso:
projects/project/locations/location/schemaRegistry/schema_registry/mode
- Percorso:
Modalità soggetto a livello di registro:si applica a un soggetto specifico all'interno dell'intero registro di schema.
- Percorso:
projects/project/locations/location/schemaRegistries/schema_registry/mode/subject
- Percorso:
Sono supportate le seguenti modalità:
Readonly: in questa modalità, il registro di schemi o i soggetti specificati non possono essere aggiornati. Le modifiche, come l'aggiornamento delle configurazioni o l'aggiunta di nuove versioni dello schema, vengono impedite.Readwrite: questa modalità consente operazioni di scrittura limitate sul registro di schemi o sui soggetti specificati. Consente modifiche come l'aggiornamento delle configurazioni e l'aggiunta di nuove versioni dello schema. Questa è la modalità predefinita sia per i nuovi registri di schema sia per i nuovi soggetti.
Quando si determina se una modifica è consentita per un soggetto specifico, la modalità impostata a livello di soggetto ha la precedenza sulla modalità impostata a livello di registro di schemi.
Ad esempio, se un registro dello schema è in modalità Readonly, ma un argomento specifico
al suo interno è in modalità Readwrite, le modifiche a quell'argomento specifico sono
consentite. Tuttavia, la creazione di nuovi soggetti è limitata dalla modalità
Readonly a livello di registro.
Esempio per la modalità dello schema
Prendi in considerazione un registro di schemi con la modalità impostata su Readwrite. Questa configurazione
consente di aggiungere nuovi soggetti al registro e nuove
versioni dello schema ai soggetti esistenti.
Supponiamo che tu abbia un argomento denominato production-config che vuoi proteggere da modifiche accidentali. Hai impostato la modalità per l'argomento
production-config su Readonly. Di conseguenza, al soggetto production-config si applicano le seguenti condizioni:
Non puoi aggiungere nuove versioni dello schema all'oggetto.
Non puoi aggiornare la configurazione (ad esempio il tipo di compatibilità) per il soggetto.
Gli altri soggetti nel registro per i quali non è stata impostata esplicitamente una modalità rimangono in modalità
Readwrite, quindi puoi comunque modificarli.Puoi continuare a creare oggetti nel registro perché il registro stesso è ancora in modalità
Readwrite.
In un secondo momento, potresti decidere di mettere l'intero registro di schemi in stato di manutenzione
impostando la modalità a livello di registro su Readonly. Tuttavia, hai
un altro oggetto, staging-config, che deve rimanere modificabile per i test
in corso. Hai impostato esplicitamente la modalità per l'argomento staging-config su
Readwrite. Di conseguenza, al soggetto staging-config si applicano le seguenti condizioni:
Il registro di schema è ora
Readonly. Non puoi creare nuovi soggetti.La maggior parte dei soggetti esistenti, come quelli senza un override di modalità specifico, diventa
Readonlyper ereditarietà. Non puoi aggiungere nuove versioni dello schema né aggiornare le relative configurazioni.L'oggetto
production-configrimaneReadonlycome impostato esplicitamente.L'argomento
staging-configrimane in modalitàReadwriteperché la sua impostazione a livello di argomento sostituisce la modalitàReadonlya livello di registro. Puoi continuare ad aggiungere versioni dello schema e aggiornare le configurazioni perstaging-config.
Questo approccio gerarchico offre flessibilità nella gestione delle modifiche allo schema a diversi livelli di granularità.
Per ulteriori informazioni su come aggiornare la modalità dello schema, consulta Aggiornare la modalità dello schema.
Configurazione consigliata per utilizzare il registro di schema in produzione
Per proteggere gli schemi in un ambiente di produzione, applica le seguenti configurazioni:
Impedisci la registrazione di nuovi schemi impostando
mode=READONLYper l'intero registro di schemi o per argomenti di produzione specifici.Impedisci ai client Kafka di creare nuove versioni dello schema assicurandoti che non dispongano dell'autorizzazione
create version.Nei serializzatori del client Kafka, imposta
auto.register.schemas=false. Per Kafka Connect, configura questa impostazione per i serializzatori di chiavi e valori come necessario:key.serializer.auto.register.schemas=falsevalue.serializer.auto.register.schemas=false
(Facoltativo) Per forzare i client a utilizzare lo schema più recente per un argomento, imposta
use.latest.version=truenel serializzatore o nel deserializzatore. Questa impostazione indica al client di utilizzare l'ultima versione dello schema registrata per l'argomento, anziché la versione corrispondente al messaggio specifico.