Kem Intensif Pembangunan Bahagian Belakang FastAPI · Pelajaran

Pendaftaran Skema dan Evolusi Kontrak Avro

Kuatkuasakan kontrak peristiwa dengan pendaftaran skema dan kembangkan muatan menggunakan peraturan keserasian.

Pelajaran 2 daripada 413 langkah

Pendaftaran Skema dan Evolusi Kontrak Avro ialah pelajaran Kem Intensif Pembangunan Bahagian Belakang FastAPI percuma di CoddyKit. Ini ialah pelajaran 2 daripada 4. Sebanyak 3 pelajaran dalam laluan pembelajaran ini boleh dibaca sepenuhnya secara percuma — selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan praktikal dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Pelajaran ini merupakan sebahagian daripada laluan pembelajaran Kem Intensif Pembangunan Bahagian Belakang FastAPI, dan kemajuan anda disegerakkan merentas web serta aplikasi CoddyKit. Kursus Kem Intensif Pembangunan Bahagian Belakang FastAPI merangkumi sejumlah 4 pelajaran.

Mengapa Kontrak Peristiwa Memerlukan Daftar

Dalam bahagian belakang FastAPI dipacu peristiwa, perkhidmatan anda menerbitkan peristiwa ke Kafka atau Pulsar dan banyak pengguna bebas membacanya. Muatan peristiwa ialah kontrak: pengeluar dan pengguna mesti bersetuju tentang nama medan, jenis dan struktur.

  • Jika pengeluar menamakan semula user_id kepada userId, setiap pengguna rosak secara senyap.
  • JSON biasa tidak mempunyai bentuk yang dikuatkuasakan, jadi kesilapan ejaan terus dihantar ke persekitaran produksi.

Daftar Skema menyimpan skema berversi secara berpusat dan menolak mesej yang melanggar kontrak yang dipersetujui, lalu memisahkan pasukan sambil memastikan data selamat.

Avro: Format Padat Berasaskan Skema

Apache Avro ialah format pensirian yang paling biasa digunakan bersama daftar skema. Setiap rekod diterangkan oleh skema JSON, dan muatan perduaan itu sendiri tidak membawa nama medan, hanya nilai, menjadikannya padat.

  • Skema mentakrifkan name, type, fields dan nilai default pilihan.
  • Pembaca memerlukan skema untuk menyahkod bait, dan itulah sebabnya daftar tersebut wujud.

Di bawah ialah skema Avro minimum untuk peristiwa OrderCreated.

order_created_schema = {
    "type": "record",
    "name": "OrderCreated",
    "namespace": "com.shop.events",
    "fields": [
        {"name": "order_id", "type": "string"},
        {"name": "user_id", "type": "string"},
        {"name": "amount_cents", "type": "long"},
        {"name": "currency", "type": "string"},
    ],
}

print(order_created_schema["name"], "has", len(order_created_schema["fields"]), "fields")

Mensiri Rekod dengan fastavro

Pustaka Python tulen fastavro membolehkan anda mengekod dan menyahkod rekod Avro tanpa broker. Susun atur bait ini sama seperti yang akan dihantar oleh pengeluar anda ke Kafka.

  • parse_schema mengesahkan skema sekali.
  • schemaless_writer menulis badan perduaan; schemaless_reader menyahkodnya.

Perhatikan bahawa bait yang dikodkan hanya mengandungi nilai, bukan nama medan.

import io
from fastavro import parse_schema, schemaless_writer, schemaless_reader

schema = parse_schema({
    "type": "record",
    "name": "OrderCreated",
    "fields": [
        {"name": "order_id", "type": "string"},
        {"name": "amount_cents", "type": "long"},
    ],
})

record = {"order_id": "o-123", "amount_cents": 4999}

buf = io.BytesIO()
schemaless_writer(buf, schema, record)
encoded = buf.getvalue()
print("encoded bytes:", encoded)

buf.seek(0)
decoded = schemaless_reader(buf, schema)
print("decoded:", decoded)

Format Wayar Confluent

Apabila anda menerbitkan melalui daftar, nilainya bukan Avro mentah. Pensiri Confluent menambahkan pengepala 5 bait supaya pengguna tahu skema yang perlu diambil.

  • Bait 0: bait ajaib, sentiasa 0x00.
  • Bait 1-4: ID skema 4 bait tertib big-endian.
  • Baki bait: badan Avro tanpa skema.

Pengguna membaca ID tersebut, memuat turun versi skema yang tepat daripada daftar, kemudian menyahkod badan. Inilah cara muatan lama dan baharu wujud bersama pada topik yang sama.

import struct

MAGIC = 0
schema_id = 42
avro_body = b"\x0co-1234\x9eL"  # pretend Avro bytes

frame = struct.pack(">bI", MAGIC, schema_id) + avro_body
print("wire bytes:", frame)

magic, sid = struct.unpack(">bI", frame[:5])
print("magic:", magic, "schema_id:", sid)
print("body:", frame[5:])

Mendaftarkan Skema semasa Permulaan FastAPI

Pola yang kemas ialah mendaftarkan skema pengeluar anda sekali semasa permulaan aplikasi menggunakan API REST daftar. Daftar tersebut mengembalikan ID skema yang stabil untuk digunakan semula bagi setiap mesej.

  • Subjek secara lalai mengikut konvensyen <topic>-value.
  • Mendaftarkan skema yang sama adalah idempoten: anda menerima ID yang sama semula.

Coretan ini menghantar skema Avro kepada daftar yang serasi dengan Confluent.

import json
import httpx

REGISTRY_URL = "http://schema-registry:8081"

async def register_schema(subject: str, avro_schema: dict) -> int:
    payload = {"schema": json.dumps(avro_schema)}
    async with httpx.AsyncClient() as client:
        resp = await client.post(
            f"{REGISTRY_URL}/subjects/{subject}/versions",
            json=payload,
            headers={"Content-Type": "application/vnd.schemaregistry.v1+json"},
        )
        resp.raise_for_status()
        return resp.json()["id"]

# Called inside FastAPI's lifespan startup:
# schema_id = await register_schema("orders-value", order_created_schema)

Mod Keserasian: Keputusan Teras

Daftar menguatkuasakan dasar evolusi bagi setiap subjek. Mod yang anda pilih menentukan perubahan skema yang dibenarkan dan menetapkan susunan naik taraf anda.

  • BACKWARD (lalai): skema baharu boleh membaca data yang ditulis oleh skema sebelumnya. Naik taraf pengguna dahulu.
  • FORWARD: skema sebelumnya boleh membaca data yang ditulis oleh skema baharu. Naik taraf pengeluar dahulu.
  • FULL: kedua-dua arah dipenuhi. Susunan tidak penting.
  • *_TRANSITIVE: pemeriksaan dijalankan terhadap semua versi terdahulu, bukan versi terkini sahaja.

Kebanyakan pasukan menggunakan BACKWARD sebagai lalai kerana pengguna biasanya ketinggalan berbanding pengeluar.

Perubahan Serasi Ke Belakang: Tambah Medan Dengan Nilai Lalai

Di bawah keserasian BACKWARD, anda boleh menambah medan hanya jika medan itu mempunyai nilai lalai. Pengguna yang menggunakan skema baharu ketika membaca mesej lama hanya mengisi nilai lalai; medan yang dibuang juga memerlukan medan lama mempunyai nilai lalai.

  • Menambah discount_cents dengan default: 0 adalah selamat.
  • Menambahnya tanpa nilai lalai akan ditolak kerana rekod lama tidak mempunyai nilai untuk dibekalkan.

Versi baharu di bawah mengembangkan peristiwa pesanan dengan selamat.

order_v2 = {
    "type": "record",
    "name": "OrderCreated",
    "namespace": "com.shop.events",
    "fields": [
        {"name": "order_id", "type": "string"},
        {"name": "user_id", "type": "string"},
        {"name": "amount_cents", "type": "long"},
        {"name": "currency", "type": "string"},
        # NEW field is backward compatible ONLY because of the default
        {"name": "discount_cents", "type": "long", "default": 0},
    ],
}

print("fields in v2:", [f["name"] for f in order_v2["fields"]])

Membaca Bait Lama Dengan Skema Baharu

Avro menyelesaikan perbezaan antara skema penulis (digunakan untuk mengekod) dan skema pembaca (digunakan untuk menyahkod). Apabila pembaca mempunyai medan baharu dengan nilai lalai, penyahkodan bait lama memasukkan nilai lalai itu secara automatik.

  • Hantar kedua-dua skema kepada schemaless_reader sebagai pembaca dan penulis.
  • discount_cents yang tiada akan muncul sebagai nilai lalainya, 0.

Inilah yang menjadikan evolusi BACKWARD tidak memecahkan sistem dalam produksi.

import io
from fastavro import parse_schema, schemaless_writer, schemaless_reader

writer = parse_schema({
    "type": "record", "name": "OrderCreated",
    "fields": [{"name": "order_id", "type": "string"},
               {"name": "amount_cents", "type": "long"}],
})
reader = parse_schema({
    "type": "record", "name": "OrderCreated",
    "fields": [{"name": "order_id", "type": "string"},
               {"name": "amount_cents", "type": "long"},
               {"name": "discount_cents", "type": "long", "default": 0}],
})

buf = io.BytesIO()
schemaless_writer(buf, writer, {"order_id": "o-9", "amount_cents": 1500})
buf.seek(0)
out = schemaless_reader(buf, writer, reader)
print(out)  # discount_cents filled from default

Perubahan Memecahkan Sistem yang Ditolak oleh Daftar

Sesetengah penyuntingan tidak mungkin serasi dan pemeriksaan keserasian daftar (permintaan awal POST .../compatibility/subjects/<s>/versions/latest) akan mengembalikan is_compatible: false.

  • Menamakan semula medan (ia menjadi penambahan + pembuangan tanpa alias).
  • Menukar jenis dengan cara yang tidak serasi, contohnya string kepada long.
  • Menambah medan wajib tanpa nilai lalai di bawah BACKWARD.

Untuk menamakan semula dengan selamat, gunakan alias Avro supaya pembaca memetakan nama lama kepada nama baharu.

# Safe rename using aliases: old name "user_id" -> new "customer_id"
renamed = {
    "type": "record",
    "name": "OrderCreated",
    "fields": [
        {"name": "order_id", "type": "string"},
        {
            "name": "customer_id",
            "type": "string",
            "aliases": ["user_id"],
        },
        {"name": "amount_cents", "type": "long"},
    ],
}

for f in renamed["fields"]:
    print(f["name"], f.get("aliases", []))

Memeriksa Keserasian dalam CI Sebelum Pelancaran

Kesannya, perubahan yang memecahkan sistem dapat dikesan sebelum sampai ke broker dengan memanggil titik akhir keserasian daftar daripada saluran paip CI anda. Jika skema yang dicadangkan tidak serasi, gagalkan binaan.

  • Ini melindungi setiap pengguna tanpa menjalankan satu mesej pun melalui Kafka.
  • Jalankannya sebagai langkah dalam kerja yang sama yang membina imej FastAPI anda.

Pembantu ini mengembalikan True hanya apabila daftar meluluskan versi baharu.

import json
import httpx

REGISTRY_URL = "http://schema-registry:8081"

async def is_compatible(subject: str, new_schema: dict) -> bool:
    url = f"{REGISTRY_URL}/compatibility/subjects/{subject}/versions/latest"
    async with httpx.AsyncClient() as client:
        resp = await client.post(
            url,
            json={"schema": json.dumps(new_schema)},
            headers={"Content-Type": "application/vnd.schemaregistry.v1+json"},
        )
        resp.raise_for_status()
        return resp.json()["is_compatible"]

# In CI:
#   ok = await is_compatible("orders-value", order_v2)
#   if not ok: raise SystemExit("Schema change is incompatible")

Menghasilkan dan Menggunakan dengan confluent-kafka

Dalam produksi, anda membiarkan pensiri mengendalikan format wayar dan carian daftar. confluent-kafka AvroSerializer mendaftarkan skema, menambahkan ID dan mengekod badan; AvroDeserializer melakukan proses sebaliknya.

  • Pensiri menyimpan ID skema dalam cache, jadi daftar jarang diakses.
  • Pengguna secara telus mengambil apa sahaja skema penulis yang digunakan untuk mengekod setiap mesej.

Inilah penghubung antara penerbit peristiwa FastAPI anda dengan perkhidmatan hiliran.

from confluent_kafka.schema_registry import SchemaRegistryClient
from confluent_kafka.schema_registry.avro import AvroSerializer
from confluent_kafka import Producer

sr = SchemaRegistryClient({"url": "http://schema-registry:8081"})

schema_str = '''
{"type":"record","name":"OrderCreated",
 "fields":[{"name":"order_id","type":"string"},
          {"name":"amount_cents","type":"long"}]}
'''

serializer = AvroSerializer(sr, schema_str)
producer = Producer({"bootstrap.servers": "kafka:9092"})

# producer.produce(topic="orders",
#   value=serializer({"order_id": "o-1", "amount_cents": 999}, ctx))

Semakan Ringkas: Memilih Mod Keserasian

Pasukan anda perlu menambah medan pilihan baharu pada peristiwa Kafka, dan anda tidak boleh menggunakan semula setiap pengguna pada saat yang sama dengan pengeluar. Pengguna biasanya ketinggalan berbanding pengeluar dalam pelancaran.

Ringkasan: Kontrak yang Berkembang dengan Selamat

Sekarang anda tahu cara menguatkuasakan dan mengembangkan kontrak peristiwa dalam bahagian belakang FastAPI dipacu peristiwa.

  • Daftar Skema menyimpan skema berversi dan mengeluarkan ID skema yang disematkan dalam format wayar Confluent (bait ajaib + ID 4 bait + badan Avro).
  • Avro memisahkan skema penulis dan pembaca, lalu menyelesaikan perbezaan melalui nilai lalai dan alias.
  • BACKWARD (lalai yang biasa) bermaksud skema baharu membaca data lama: tambah medan hanya dengan nilai lalai, dan naik taraf pengguna dahulu.
  • FORWARD menaik taraf pengeluar dahulu; FULL membenarkan mana-mana susunan; varian TRANSITIVE memeriksa semua versi terdahulu.
  • Jalankan pemeriksaan keserasian dalam CI daftar untuk menyekat perubahan yang memecahkan sistem sebelum sampai ke Kafka atau Pulsar.

Anggap skema anda sebagai kod: versikan, semak dan biarkan daftar melindungi kontrak tersebut.

Percuma untuk bermula

Pelajari Kem Intensif Pembangunan Bahagian Belakang FastAPI dengan tutor kecerdasan buatan — percuma

Tulis dan jalankan kod sebenar dalam pelayar anda, dapatkan bantuan segera daripada tutor kecerdasan buatan yang tersedia 24/7, dan sambung semula dari tempat anda berhenti di web atau dalam aplikasi.

Kursus
21
Pelajaran
84

Soalan Lazim

Adakah pelajaran “Pendaftaran Skema dan Evolusi Kontrak Avro” percuma?

Ya — sebanyak 3 pelajaran dalam laluan pembelajaran Kem Intensif Pembangunan Bahagian Belakang FastAPI, termasuk “Pendaftaran Skema dan Evolusi Kontrak Avro”, boleh dibaca sepenuhnya secara percuma di web ini. Selepas itu, CoddyKit PRO membuka akses kepada semua pelajaran, serta latihan interaktif dengan penyunting kod terbina dalam dan tutor kecerdasan buatan yang tersedia 24/7. Kursus Kem Intensif Pembangunan Bahagian Belakang FastAPI merangkumi sejumlah 4 pelajaran.

Apakah yang akan saya pelajari dalam “Pendaftaran Skema dan Evolusi Kontrak Avro”?

Kuatkuasakan kontrak peristiwa dengan pendaftaran skema dan kembangkan muatan menggunakan peraturan keserasian. Anda berlatih Kem Intensif Pembangunan Bahagian Belakang FastAPI menggunakan kod praktikal yang dijalankan terus dalam pelayar, manakala tutor kecerdasan buatan 24/7 menjawab soalan anda semasa anda mengikuti pelajaran.

Adakah saya memerlukan pengalaman untuk memulakan Kem Intensif Pembangunan Bahagian Belakang FastAPI?

Tiada pengalaman terdahulu diperlukan. Pembelajaran Kem Intensif Pembangunan Bahagian Belakang FastAPI di CoddyKit disusun untuk pelajar daripada peringkat pemula hingga lanjutan, jadi anda boleh bermula di sini atau dari awal dan belajar mengikut kadar anda sendiri. Ini ialah pelajaran 2 daripada 4.

Berapa lamakah pelajaran “Pendaftaran Skema dan Evolusi Kontrak Avro” diambil?

Kebanyakan pelajaran CoddyKit mengambil masa kira-kira 5–10 minit. Setiap pelajaran ringkas dan interaktif, jadi anda boleh membuat kemajuan secara berterusan dan menyambung tepat dari tempat anda berhenti di web atau aplikasi.

Bolehkah saya menulis dan menjalankan kod dalam pelajaran Kem Intensif Pembangunan Bahagian Belakang FastAPI ini?

Ya. Setiap pelajaran Kem Intensif Pembangunan Bahagian Belakang FastAPI menyertakan penyunting kod terbina dalam, jadi anda boleh menulis dan menjalankan kod sebenar terus dalam pelayar serta menerima maklum balas kecerdasan buatan serta-merta — tanpa memerlukan persediaan setempat.

Semua pelajaran dalam kursus ini

  1. Menghasilkan dan Menggunakan Peristiwa Kafka Secara Tak Segerak
  2. Pendaftaran Skema dan Evolusi Kontrak Avro
  3. Corak Peti Keluar Transaksi
  4. Pengguna Idempoten dan Semantik Tepat Sekali
← Kembali ke Kem Intensif Pembangunan Bahagian Belakang FastAPI