Compatibilità API contrattuale
Perché è necessaria la compatibilità contrattuale
La compatibilità contrattuale è la capacità dell'API di evolversi senza compromettere le integrazioni esistenti. I sistemi API in crescita cambiano più spesso di codice client; La compatibilità permette di rilasciare fici in modo iterativo, senza fare «grandi spostamenti».
L'idea chiave è che il contratto è primario, le modifiche seguono le regole di compatibilità e vengono verificate automaticamente.
Concetti di base
Il contratto è una specifica formale dell'interfaccia: risorse/metodi/eventi, schemi di dati, codici di errore, limiti, SLA, requisiti di sicurezza.
Il provider è il proprietario dell'API. Consumer - client/integrazione.
- Backward: il nuovo fornitore lavora con i clienti più vecchi.
- Forward: il vecchio fornitore lavora con i nuovi consumatori (di solito raggiunti da «lettori tolleranti»).
- Full: sono stati rispettati sia backward che forward (l'opzione più forte).
- Adduttività - Aggiunge elementi facoltativi senza rompere quelli esistenti.
Criteri di versioning
Versioning semantico (consigliato):- MAJOR - Modifiche distruttive (solo al rilascio della nuova API: '/v2 ',' service. v2`).
- MINOR - Modifiche additive (nuovi campi/metodi opzionali).
- PATCH - Correzioni senza modificare il contratto.
- Deprecation Policy: dichiarazione di elementi obsoleti, finestra di supporto (sunset), avvisi in intestazioni/metadati, piano di rimozione.
Modifiche sicure vs pericolose
Sicuro (di solito backward-compatibile)
Aggiunge un campo facoltativo a JSON/Protobuf/Avro.
Aggiunge un nuovo endpoint/metodo/evento.
Espansione enum con nuovi valori se i consumatori sono tolleranti con valori sconosciuti.
Aumento dei limiti (ad esempio «maxItems») senza limitare i limiti minimi.
Aggiunge nullable con default corretti.
Modifica il testo delle descrizioni/esempi.
Pericolosi (compromettono la compatibilità)
Rinomina o rimuove i campi, ne modifica il tipo o l'obbligatorietà.
Cambio di semantica stato-codice/errore (ad esempio, «200», «204» o «404»).
Modifica del formato ID (UUID).
Rafforzamento della validazione (minimi o pattern) senza versione.
Modifica dell'ordine e della struttura negli striam/eventi gRPC.
Riutilizza i numeri di tag in Protobuf per i nuovi campi.
Interoperabilità
REST/HTTP + JSON Schema
Additività: contrassegniamo i nuovi campi come «optional »/« nullable».
Tolerant Reader del client: ignora campi sconosciuti Non fare affidamento sull'ordine.
Versioning: maggiore - in viaggio ('/v2 ') o in mediatip (' application/vnd. example. v2+json`).
ETAG/If-Match per update sicuri senza corse.
Errore: formato unico ('type', 'code', 'title', 'detail', 'trace _ id'), non cambiare il valore dì code "senza maggiore.
Paginazione: i cursori preferiscono offset; aggiungi i campi «next _ cursor», non cambiare il significato di quelli esistenti.
gRPC / Protobuf
La numerazione dei tag è immutata. I tag eliminati non vengono riutilizzati.
I nuovi campi sono «optional »/« repeated» con default ragionevole sul server.
Non modificare l'ordine e l'obbligatorietà dei messaggi in streaming-RPC.
Gli stati di errore sono stabili ('INVALID _ ARGEMENT', 'FAILED _ PRECISION', ecc.); Nuova semantica per una nuova versione del metodo/servizio.
Event-driven (Kafka/NATS/Pulsar) + Avro/JSON Schema
Denominazione eventi: 'domain. action. v{major}`.
Nuovi campi - opzionali; evidenziare il nucleo e l'arricchimento ('.enriched').
Minuscoli di schema: regole di compatibilità (BACKWARD/FORWARD/FULL) per tema/evento.
L'estensione enum è accettabile con tolerant reader al lato dei consumatori.
Cambia la chiave di partizionamento/ordine per l'aggregazione = modifiche che rompono.
GraphQL
Aggiungere campi/tipi è sicuro; Elimina/rinomina solo tramite @ deprecated e la finestra di migrazione.
Non cambiare il tipo/non nullabile senza maggiore.
Controlla complexity/depth - i limiti fanno parte del contratto.
Modelli di evoluzione sostenibile
Additive-first - Espandi senza rompere.
Capability negotion: i client comunicano che supportano (intestazioni/impostazioni/accordi) e il server è in fase di configurazione.
Limiti del contratto: fissa MGC (contratto minimo di garanzia) e separa le estensioni (modello di piramide inversa).
Tolerance by default - I client ignorano e gestiscono correttamente valori enum sconosciuti (fallback).
Dual-write/Dual-emit: in caso di modifiche maggiori, rilasciare «v1» e «v2» in parallelo.
Sunset headers/Events: notifica la cancellazione in anticipo.
Governance e automazione
Linter API:- Nome, paginazione, codici di errore, formati di campo.
- Boof/Protobuf: impedisce il riutilizzo dei tag, la notifica dei pacchetti.
- AsyncAPI/Schema Registry: compatibilità degli schemi a livello CI.
- Directory contratti (SSOT) - Registro di diagrammi/versioni centralizzato con cronologia dei diffusi.
- API Wild è un comitato/gild che adotta regole, modelli e modifiche.
- Change Management: RFC/ADR, release note, gate migratorie.
Test di compatibilità
Schema-differf in CI - Blocca i cambiamenti dello speck spezzanti (OpenAPI-diff, Buf breaking, SR compatibility).
Consumer-Driven Contracts (CDC): Pact/simili - verifica del fornitore contro i contratti dei consumatori specifici.
Golden sample: richieste/risposte di riferimento e eventi per la regressione.
E2E Canary: dislocazione per quota di traffico/singoli gruppi consumatori.
Chaos/latency - Verifica timeout/retrai - La modifica latency-SLO è considerata una modifica del contratto.
Migrazioni e deprecati
1. Dichiarare il deprecato: contrassegna l'elemento, specifica la scadenza sunset e l'alternativa.
2. Mantenere il periodo di compatibilità dual-write/dual-emit, ponti, adattatori.
3. Raccogliete la telemetria, chi altro usa il vecchio?
4. Comunicazione: newsletter, promemoria, banco di prova.
5. Ritiro: al termine della finestra, eliminazione con rilascio fisso.
Esempi di modifiche
REST
C'era:json
{ "id":"p1", "status":"authorized" }
Acciaio (additivo, sicuro):
json
{ "id":"p1", "status":"authorized", "risk_score": 0. 12 }
I client che ignorano campi sconosciuti non si rompono.
Protobuf
proto message Payment {
string id = 1;
string status = 2; // don't change tag numbers optional double risk_score = 3; // additive
}
Event
`payment. authorized. v1 '(kernel) +' payment. enriched. v1 '(arricchimento). I consumatori del percorso critico leggono il nucleo e non dipendono dall'arricchimento.
Antipattern
Swagger-wash - La specifica esiste formalmente, ma il comportamento del servizio è diverso.
Breaking by stealth - Hanno cambiato il tipo/stato/formato senza una nuova versione e una nuova finestra di migrazione.
Eventi CDC crudi come un contratto pubblico: la perdita di schemi di database, l'impossibilità di evoluzione.
Client rigido: cade con campi/valori sconosciuti; assenza di tolerant reader.
Riutilizzo dei tag protobuf: corruzione dei dati silenziosa.
La latitanza come «non-regolamentare» è stata improvvisamente estesa a p95 - i consumatori si rompono per timeout.
Foglio di assegno compatibile (prima del murge)
- Le modifiche sono additive (o la versione maggiore è stata preparata).
- Gli assegni Linter/diff sono stati superati, le regole di compatibilità sono verdi.
- Gli errori/codici/stati non hanno modificato la semantica.
- Enum estesi senza il divieto dei vecchi valori; clienti - tolerant.
- I limiti MGC sono invariati.
- Aggiornati esempi/documentazione/SDK.
- Per la maggiore è il piano dual-write/dual-emit, sunset-data, comm-plan.
- I test CDC/Golden/E2E sono stati completati.
FAQ
Cosa differisce il backward dalla compatibilità forward?
Backward - I nuovi server non compromettono i vecchi clienti. Forward - I nuovi client non si rompono sui vecchi server (attraverso tolerant reader e default accurati).
Quando si fa «/v2 »?
Quando gli invarianti/semantici cambiano, i campi/metodi vengono eliminati, è necessario un nuovo modello di protezione, più semplice e onesto.
Possiamo vivere senza Schema Registry/Linter?
Teoricamente, si ', sono praticamente regressi frequenti e astinenze nascoste. L'automazione paga.
Enum può essere esteso?
Sì, se i client gestiscono correttamente valori sconosciuti (fallback/ignore). Altrimenti, maggiore.
Totale
Compatibilità contrattuale - regole + disciplina + automazione. Progettate in modo additivo, versionate le modifiche che rompono, applicate tolerant reader, controllate i diffusi e il CDC, pianificate il deprecato. In questo modo le API possono evolversi rapidamente e le integrazioni rimanere stabili.