Kompatybilność wsteczna
Czym jest kompatybilność wsteczna
Kompatybilność wsteczna - właściwość systemu do akceptacji i prawidłowego przetwarzania starych klientów/konsumentów po aktualizacji systemu. Prostsze: wypuszczasz nową wersję serwisu/zdarzeń, a istniejące integracje nadal działają bez zmian.
Klucz: nie łamać umów. Każda ewolucja polega na dodawaniu, a nie przerabianiu, już wydanego.
Podstawowe zasady
1. Dodatek pierwszy
Opcjonalnie dodawane są nowe pola/metody/zdarzenia. Nic nie jest usuwane i nie zmienia znaczenia.
2. Minimalna umowa gwarancyjna (MGC)
Zdefiniuj jądro - zbiór pól/operacji, bez których skrypt traci swoje znaczenie. Rdzeń jest stabilny. Cała reszta to przedłużenia.
3. Czytnik tolerancyjny
Klienci ignorują nieznane pola i prawidłowo obsługują nowe wartości enum (fallback).
4. Zasady dotyczące wersji
Zerwanie zmian - tylko przez główną linię ('/v2 ',' płatności. v2 „,” wydarzenie. v2 "). Drobny - dodatek.
5. Obserwowalność - część umowy
Wersja klienta, format, flagi funkcji są widoczne w logach/utworach i metrykach. Umożliwia to zarządzanie migracją.
Bezpieczne vs niebezpieczne zmiany
Ogólnie bezpieczne (BC-OK)
Dodaj pola opcjonalne (JSON/Avro/Protobuf 'opcjonalne '/' nieważne').
Dodaj nowe punkty końcowe/metody/zdarzenia.
Rozszerzenie enum z dodatkowymi wartościami (z czytnikiem tolerancyjnym).
Osłabienie walidacji (maksymalizacja, dodanie formatów alternatywnych).
Dodaj nieistotne nagłówki/metadane.
Niebezpieczne (łamanie)
Usuń/zmień nazwę pola, zmień typ lub obowiązkowe pola.
Zmiana semantyki kodu statusu/błędu.
Ponowne użycie znaczników protobufu dla innych pól.
Zmiana klucza podziału zdarzeń (łamie kolejność agregatu).
Zaostrzenie SLAs/timeouts, co powoduje, że starzy klienci zaczynają spadać.
Style interakcji
REST/HTTP + JSON
Dodatkowość: nowe pola - 'opcjonalne', serwer nie wymaga ich od starych klientów.
Wersje: główne - w tranzycie („/v2 ”) lub typ nośnika; drobne - poprzez rozszerzenia i "? include = '/'? pola = '.
Błędy: jednolity format; nie zmieniać kodów/semantyki bez większych.
ETag/If-Match: dla bezpiecznych aktualizacji bez wyścigów.
Idempotencja: „Idempotency-Key” dla POST - starzy klienci nie „podwajają” wpływu na rekolekcje.
gRPC/Protobuf
Znaczniki są niezmienione. Usunięte znaczniki nie mogą być ponownie użyte.
Nowe pola - „opcjonalne ”/„ powtarzane”; wartości domyślne są obsługiwane poprawnie przez stary kod.
Streaming: nie zmieniaj zamówienia/obowiązku wiadomości w małym.
Błędy - stabilny zestaw statusów; nowa semantyka → nowa metoda/usługa ('.v2').
Napędzane zdarzeniami (Kafka/NATS/Pulsar) + Avro/JSON/Proto
Nazwa: 'domena. działania. v {major} '.
Rdzeń vs Wzbogacony: rdzeń stabilny; wzbogacanie - poszczególne typy/tematy („.enriched”).
Tryb kompatybilności schematu: częściej BACKWARD; CI blokuje niezgodne zmiany.
Podział: klucz (na przykład "payment _ id') - część umowy; zmień go - łamanie.
GraphQL
Dodawanie pól/typów - OK; usuń/zmień nazwę - poprzez '@ deprecated' i okno migracji.
Nie podnosić „nieważne → nieważne” bez większych.
Monitoruj złożoność/głębokość - zmiana limitu = zmiana kontraktu.
Wzory, które pomogą zachować BC
Model odwrotnej piramidy: ustabilizować rdzeń, rozszerzyć opcjonalnie.
Negocjacja funkcji: obsługiwane funkcje raportów klienta ('X-Capabilities '/handshake), serwer się dostosowuje.
Dual-run/dual-emit: Przechowywać 'v1' i 'v2' w tym samym czasie podczas migracji.
Adaptery: serwery proxy/bramki tłumaczą żądania dla „ciężkich” klientów.
Rozszerzenie i kontrakt (dla DB): najpierw dodaj nowy, zacznij pisać/czytać, a dopiero wtedy usuń stary.
Zarządzanie i proces
1. Katalog umów (Schema Registry): Pojedyncze źródło prawdy z zasadami zgodności.
2. Linters and diff checks in CI/CD: OpenAPI-diff, Buf-breaking, Avro/JSON Schema check compatibility.
3. CDC/Consumer-Driven Contracts: Dostawca jest testowany pod kątem rzeczywistych umów konsumenckich.
4. Złote próbki: zapytania referencyjne/odpowiedzi/zdarzenia dla regresji.
5. Zarządzanie zmianą: RFC/ADR w sprawie łamania, planów zachodu słońca, komunikacji.
Deprekate i usuwanie starych wersji
Znak przestarzały ('@ deprecated', opisy, nagłówki 'Deprecation', 'Sunset').
Okno migracji: data wstępnie ogłoszona, ławka testowa, przykłady kodów.
Telemetria użycia: Kto jeszcze jest na 'v1'? mierniki/dzienniki segmentu według wersji.
Dual-run do zero ruchu, a następnie usunąć.
Obserwowalność i wskaźniki operacyjne
Procent żądań/wiadomości według wersji.
Udział błędów/terminów dla starszych klientów po zwolnieniu.
Odsetek niekompatybilnego ładunku użytkowego (walidacja przez schemat na filtrach bramy/strumienia).
Opóźnienie migracji konsumentów (ile więcej słuchać 'v1').
Wsteczne testowanie zgodności
Schema-diff: fail мра remove/rename/type-change.
Testy kontraktowe: stare SDK/klienci ścigają się z nową implementacją.
E2E canary: część starego ruchu do nowej wersji, porównanie p95/p99, kody, przekładki.
Powtórka zdarzeń: Projekcje są zbierane przez nową logikę ze starego dziennika bez rozbieżności.
Zastrzyk błędu: opóźnienia/częściowe odpowiedzi - starzy klienci nie spadają.
Przykłady
REST (dodatek)
To było:json
{ "id": "p1", "status": "authorized" }
Stało się to:
json
{ "id": "p1", "status": "authorized", "risk_score": 0. 12 }
Starzy klienci, ignorując 'risk _ score', kontynuują pracę.
Protobuf (tagi)
proto message Payment {
string id = 1;
string status = 2;
optional double risk_score = 3 ;//new field, safe
}
//Tags 1 and 2 cannot be changed/deleted without v2
Wydarzenia (rdzeń + wzbogacenie)
"płatność. autoryzowany. v1 '- jądro (minimalne fakty).
"płatność. wzbogacony. v1 "- części; konsumenci podstawowi nie są uzależnieni od wzbogacenia.
Antypattery
Swagger-wash: schemat został zaktualizowany, ale usługa zachowuje się w stary sposób (lub odwrotnie).
Ukryte przerwy: zmienił znaczenie pola/stanu bez wersji.
Ponowne wykorzystanie znaczników protobufu: „cicha” korupcja danych.
Klienci twardzi: spadają w nieznanych polach/enum; brak tolerancyjnego czytnika.
Mega-punkt końcowy: Jeden all-in-one - każda zmiana staje się potencjalnym złomem.
Lista kontrolna przed zwolnieniem
- Zmiany są dodatkami; jądro (MGC) jest nietknięte.
- Przeszedł kontrolę linterów/diff; Nie ma żadnych złamanych flag.
- SDK klienta zostały zaktualizowane (lub nie są wymagane dla rozszerzenia dodatku).
- Aktywny czytnik tolerancyjny dla klientów; enum-fallback sprawdzone.
- Mierniki/dzienniki zawierają flagi wersji i możliwości.
- W przypadku potencjalnego pęknięcia istnieje plan „/v2 ”, plan podwójnego działania i plan zachodu słońca.
- Dokumentacja/przykłady zostały zaktualizowane, istnieją złote zestawy.
NAJCZĘŚCIEJ ZADAWANE PYTANIA
Do tyłu vs do przodu - jaka jest różnica?
Wstecz - nowe serwery współpracują ze starymi klientami. Naprzód - nowi klienci pracują prawidłowo ze starymi serwerami (ze względu na tolerancyjny czytnik i schludne domyślne). Pełne koło - pełna kompatybilność.
Czy zawsze muszę robić '/v2 'dla dużych zmian?
Tak, jeśli niezmienne/typy/klucze/semantyka złamać. W przeciwnym razie utrzymać linię i ewoluować dodatkowo.
A co z enum?
Dodaj nowe wartości bez zmiany znaczenia starych. Klienci muszą mieć nieznaną wartość.
A jeśli już „złamał”?
Rollback, hot-fix adapter, 'v2' zwolnienie z podwójnym biegiem, komunikacja i przewodnik migracyjny.
Razem
Kompatybilność wsteczna to dyscyplina ewolucji: ustabilizować jądro, dodatkowo rozszerzyć, wdrożyć tolerancyjny czytnik, zautomatyzować kontrole i utrzymać świadomą deprecację. W ten sposób można szybko rozwijać platformę bez pozostawiania klientów pod gruzami „niewidzialnych” zmian.