İçeriğe geç

Olay Şemasının Evrimi — Alanın Adını Değiştirdin, Kim Kırıldı?

Orta 8 dk Sık karşılaşılır

Önce şunu oku: Kafka — Partition, Consumer Group ve Lag

30 saniyede özet

Kafka'daki bir olayı, aynı gün güncellenmeyen birçok servis okur. Varsayılanı olan alan eklemek güvenlidir; ad ya da tür değiştirmek eski tüketicileri sessizce bozar ya da durdurur. Schema registry, uyumsuz şemayı yayından önce durdurur.

Bir bankanın havale formu var ve şubelerin bir kısmı hâlâ eski formu okuyor. Formun altına isteğe bağlı yeni bir kutu eklemek kimseyi şaşırtmaz. Ama “tutar” kutusunun adını değiştirirsen, eski formu okuyan şube tutarı bulamaz.

  1. Bayt: TransferCompleted olayında amount alanını amountMinor yaptım. Kuruş cinsinden olduğu daha açık.

  2. Sen: Testlerimiz yeşildi, yayına aldık. Şimdi bildirim servisi müşterilere 0 TL yazıyor.

  3. Bayt: Muhasebe defteri de durmuş! Onlar hâlâ amount alanını arıyor.

  4. Bayt: Olayı biz yazıyoruz, ama başkaları okuyor. Okuyanların hepsi bugün güncellenmedi.

Olay kimin?

Bir olay Kafka’ya yazıldığında onu birçok servis okuyabilir: bildirim, muhasebe, raporlama. Her biri kendi zamanında yayına çıkar; hepsi aynı gün güncellenmez.

Bu yüzden olayın biçimi bir sözleşmedir. Üreticinin kendi testleri yeşil olsa da, eski kodla okuyan bir tüketici kırılabilir.

Kafam karıştı, daha basit anlat

Olayı sen yazarsın, ama başkaları okur. Onların hepsi bugün güncellenmez.

Hızlı kontrolBaşlangıç

Bir olayı yayınlayan servis güncellendi. Olayı okuyan servisler neden sorun yaşayabilir?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Olaya varsayılan değeri olan yeni bir alan eklemek eski tüketicileri kırar mı?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Hangi değişiklik kırar?

amount alanının adı amountMinor oldu. Bildirim servisi eksik alanı hata vermeden null sayıyor. Müşteriye giden SMS ne der? Cevabı göster

“0 TL havale geldi” der. Servis amount alanını bulamaz, null’u sıfır gibi yazar ve hiçbir hata vermez. Eksik alanı kabul etmeyen muhasebe defteri ise hata verip durur.

Yeni formu basmadan eskisiyle karşılaştır.
Adım adım oku
  1. Şubeler hâlâ eski formu okuyor.
  2. Altta isteğe bağlı yeni kutu: sorun yok.
  3. Tutarın adı değişti: eski şube bulamaz.
  4. Yeni formu basmadan eskisiyle karşılaştır.

Varsayılanı olan yeni bir alan eklemek geriye uyumlulukYeni şemanın eski şemayla yazılmış verileri okuyabilmesi. Varsayılanı olan alan eklemek uyumludur; ad ya da tür değiştirmek değildir.Sözlükte gör →: eski kod onu görmezden gelir. Bir alanın adını ya da türünü değiştirmek ise uyumlu değildir.

Bir schema registryOlay şemalarının sürümlerini saklayan ve yeni bir şemayı eskileriyle karşılaştıran servis. Uyumsuz şemayı kaydetmez, böylece yayınlanamaz.Sözlükte gör →, yeni şemayı eskileriyle karşılaştırır. Uyumsuz şemayı kaydetmez; üretici olayı yayınlamadan hata alır.

Kafam karıştı, daha basit anlat

Varsayılanlı alan eklemek güvenli. Ad ya da tür değiştirmek kırar. Registry bunu yayından önce yakalar.

Hızlı kontrolOrta

amount alanının adı amountMinor yapıldı. Eksik alanı null sayan gevşek bir tüketici ne yapar?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Schema registry'nin BACKWARD uyumluluk kontrolü ne yapar?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Kendin gör

TransferCompleted olayı değişiyor

Tohum 352561

Üretici: transfer servisi (v2) → Kafka: transfer-completed

  1. Bildirim servisi (v1, gevşek okur)
  2. Muhasebe defteri (v1, katı okur)

⚠ duran: 0 · ✕ sessizce yanlış: 0

Hız
Adım 0

Şu an ne oldu?

amount alanının adı amountMinor oldu

Üretici yeni sürümde; iki tüketici hâlâ eski sürümde.

Görevler0/3

  • Müşteriye "0 TL" SMS’i gitsinaçık

    İpucu

    Alanın adını değiştir.

  • Kırıcı bir değişiklik yayınlanmadan durdurulsunaçık

    İpucu

    Registry kontrolünü aç.

  • Olay büyüsün, kimse kırılmasınaçık

    İpucu

    Varsayılanı olan alan.

Olay günlüğü (0)

Henüz olay yok. Oynat veya adımla.

  1. Varsayılanla oynat. Ad değişti, registry kapalı: bildirim servisi 0 TL yazdı, muhasebe defteri durdu.
  2. “Tür değişti” seç. İki tüketici de okuyamadı.
  3. Registry kontrolünü aç. Kırıcı şema reddedildi; olay hiç yayınlanmadı, kimse kırılmadı.
  4. “Varsayılanı olan yeni alan” seç. Registry açık da olsa kapalı da olsa kimse kırılmadı.
Hızlı kontrolOrta

amount metinden sayıya çevrildi. Katı bir tüketici ne yapar?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Bir alanın adını gerçekten değiştirmek gerekiyorsa en güvenli yol hangisi?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Tuzaklar

Adı tek seferde değiştirmek. Önce yeni alanı ekle ve bir süre ikisini birlikte yaz. Bütün tüketiciler yenisine geçince eskisini kaldır.

Bilinmeyen alanda hata veren tüketici. Tüketici, tanımadığı bir alan görünce hata verirse, en güvenli değişiklik olan alan eklemek bile onu kırar. Okurken hoşgörülü ol.

Eski olayları unutmak. Topic’te aylar önceki olaylar durur. Yeniden işlemek gerektiğinde yeni kod onları da okuyabilmelidir.

Kafam karıştı, daha basit anlat

Adı adım adım değiştir, bilinmeyen alanı görmezden gel, eski olayları da okuyabil.

Hızlı kontrolOrta

Üretici servisin kendi testleri yeşil. Değişiklik neden yine de bir şeyi kırabilir?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.
Derinleş · Havale olayı: şemayı kırmadan büyütmek 4 dosya · ~43 satır · ilk okumada atlayabilirsin
Proje dosyaları

transfer/src/main/avro/ TransferCompleted.avsc Şema: yeni alan bir varsayılanla eklendi; eski alanlar yerinde.

transfer/src/main/avro/TransferCompleted.avsc
{
"type": "record",
"name": "TransferCompleted",
"namespace": "com.bank.transfer.events",
"fields": [
{ "name": "transferId", "type": "string" },
{ "name": "amount", "type": "string", "doc": "Decimal as text, e.g. 500.00" },
{ "name": "currency", "type": "string" },
{ "name": "channel", "type": "string", "default": "MOBILE", "doc": "Added in v2 with a default, so v1 readers are unaffected" }
]
}

transfer/src/main/resources/ application.yml Üretici: Avro serializer, şemayı registry'ye kaydetmeye çalışır; uyumsuzsa yayınlamadan hata alır.

transfer/src/main/resources/application.yml
spring:
kafka:
producer:
value-serializer: io.confluent.kafka.serializers.KafkaAvroSerializer
properties:
schema.registry.url: ${SCHEMA_REGISTRY_URL}
# Never register a schema from the app: register it in CI, where an
# incompatible change fails the build instead of a publish.
auto.register.schemas: false
use.latest.version: true

notification/src/main/java/com/bank/notification/ TransferCompletedListener.java Tüketici: bilinmeyen alanları görmezden gelir, eksik alan için varsayılanı kullanır.

notification/src/main/java/com/bank/notification/TransferCompletedListener.java
@Component
class TransferCompletedListener {
private final SmsSender sms;
TransferCompletedListener(SmsSender sms) {
this.sms = sms;
}
@KafkaListener(topics = "transfer-completed", groupId = "notification")
void on(TransferCompleted event) {
// Fail loudly instead of telling a customer "0 TL".
BigDecimal amount = new BigDecimal(Objects.requireNonNull(event.getAmount(), "amount missing"));
sms.send(event.getTransferId(), "Hesabınıza " + amount + " " + event.getCurrency() + " geldi.");
}
}

transfer/ci/ check-schema.sh Registry ayarı: bu topic için uyumluluk türü BACKWARD; şemalar yayından önce kontrol edilir.

transfer/ci/check-schema.sh
# Runs in CI before deploy: is the new schema compatible with the latest one?
curl --fail -s -X POST \
-H "Content-Type: application/vnd.schemaregistry.v1+json" \
--data "{\"schema\": $(jq -Rs . < src/main/avro/TransferCompleted.avsc)}" \
"$SCHEMA_REGISTRY_URL/compatibility/subjects/transfer-completed-value/versions/latest" \
| jq -e '.is_compatible == true'

Kendini sına

Şimşek turu1/4

Bir olayı okuyan servislerin hepsi aynı gün güncellenir.

Soru 1/3İleri

Bir tüketici bilinmeyen alan görünce hata veriyor. Bu ne demektir?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Aklında kalacak üç şey

  1. 1 Bir olay, onu okuyan bütün servislerle yapılmış bir sözleşmedir. Tüketicilerin hepsi aynı gün güncellenmez.
  2. 2 Varsayılanı olan yeni alan eklemek eski tüketicileri kırmaz. Bir alanın adını ya da türünü değiştirmek ise onları sessizce bozar ya da durdurur.
  3. 3 Schema registry yeni şemayı eskileriyle karşılaştırır; uyumsuz olanı kaydetmez, böylece kırıcı değişiklik canlıya ulaşmaz.
Sonraki kapı Muhasebe defterine bir borç kaydı düştü. İstek iç ağdan gelmişti ve doğru anahtarı taşıyordu. Ama gönderen havale servisi değildi. Servisler Arası Kimlik — İç Ağdan Gelen Her İstek Güvenilir mi? · 8 dk

4 kart sonraki derste seni bekliyor

0/4 kart bu dersten toplandı