Kâğıt üzerinde tek bir iş yapan bir ödeme uç noktası düşünün: ödemeyi almak. Uygulamada ise önce stok servisini, sonra dolandırıcılık puanlamasını, sonra sadakat defterini, sonra e-postayı, sonra da analitik iş akışını çağırır — beş senkron HTTP sıçraması, her biri müşterinin dönen çarkını rehin tutar. Sakin bir salı günü her şey 300 ms'de geri döner. Bir flaş indirim sırasında sadakat servisi ağırlaşmaya başlar ve birdenbire kimse hiçbir şey satın alamaz. Karttan çekim yapıldı. Sipariş ise "başarısız oldu."
Bu, yamayabileceğiniz bir hata değildir. Bu, mimarinin size onu asla bu şekilde çalışacak biçimde inşa edilmediğini söylemesidir.
İstek-yanıt aslında neye mal olur
Senkron çağrılar basit hissettirir, çünkü düşünme biçimimizi yansıtırlar: bir soru sor, yanıtı bekle. Gizli maliyet ise zamansal bağımlılıktır (temporal coupling) — zincirdeki her servisin tam olarak aynı anda sağlıklı, hızlı ve erişilebilir olması gerekir; yoksa başarısızlığı çağıran taraf yutar.
Matematik affetmez. Her biri saygın bir %99,9 çalışma süresine sahip beş servisi zincirleyin; bileşik erişilebilirliğiniz kabaca %99,5'e düşer — ayda yaklaşık 3,6 saatlik, hiçbir tek ekibin neden olmadığı bir kesinti. Gecikme de aynı şekilde birikir: p99 üst üste yığılır ve "hızlı" uç noktanız, en kötü günündeki en yavaş bağımlılığı kadar hızlıdır ancak. Beş bağımsız sistemi, birlikte çöken kırılgan tek bir organizmaya dönüştürmüş olursunuz.
"Olay güdümlü" aslında ne anlama gelir
Yaygın efsane, olay güdümlü mimarinin "önüne bir kuyruk koymak" anlamına geldiğidir. Kuyruk yalnızca tesisattır. Asıl değişim, onun içinden neyi gönderdiğinizdedir.
İstek-yanıtta komutlar verirsiniz: "bu karttan çek," "bu stoktan düş." Çağıran taraf sonucun sahibidir ve onu bekler. Olay güdümlü bir sistemde ise olguları yayımlarsınız: OrderPlaced, PaymentCaptured. Üretici, ne olduğunu belirtir ve yoluna devam eder. Kimin dinlediğini bilmez — umursamaz da. Sadakat servisi, e-posta servisi ve analitik iş akışının her biri abone olur ve kendi programına göre tepki verir.
Komutlar, göndereni alıcıya bağlar. Olaylar bunu tersine çevirir: alıcı gönderene bağımlıdır, gönderen ise hiç kimseye.
Bu tersine çevirme, işin bütünüdür. Gelecek çeyrekte yeni bir tüketici mi var? Aynı olaya abone olur. Üreticide değişiklik yok, yeni bir senkron sıçrama yok, ödemenin bozulması için taze bir yol yok.
Asenkron ne zaman kazanır
Şu biçimleri gördüğünüzde olaylara yönelin:
- Dağıtım (fan-out). Bir şey olur ve birbiriyle ilgisiz beş sistemin bunu bilmesi gerekir. Senkron dağıtım, başarısız olmanın beş yoludur; yayımlanmış bir olay ise bir.
- Ani ve düzensiz yük. Kuyruk bir amortisördür. 10.000 siparişlik bir patlamanın, tüketiciyi devirmek yerine saniyede 500'ü rahatça işleyen bir tüketiciye doğru boşalmasını sağlar.
- Uzun süren işler. Video kodlama, rapor üretimi, KYC kontrolleri. Hiç kimse doksan saniye boyunca bir HTTP bağlantısını açık tutmamalı.
- Ekiplerin ayrıştırılması. "Bir özellik ekle" ifadesi diğer üç ekiple bir toplantı gerektirdiğinde, olaylar onların takviminizi meşgul etmeden sizin olgularınıza göre geliştirme yapmasını sağlar.
Bunların hiçbiri bedava değildir. Anlık tutarlılığı nihai tutarlılıkla takas ediyorsunuz ve bu takasın dişleri vardır. Tüketiciler idempotent olmalıdır — aynı olay iki kez teslim edilecektir ve siz bunu umursamamayı bilmelisiniz. Hata ayıklama, bir yığın izi olmaktan çıkar ve dağıtık bir zaman çizelgesine dönüşür. Sıralama garantileri incelir. Ekibiniz henüz "bu olay iki kez, sırasız ve bir saat geç gelirse ne olur?" sorusunu yanıtlayamıyorsa, asenkron, yardımcı olmadan önce canınızı yakar.
İstek-yanıtın hâlâ doğru seçim olduğu durumlar
Asenkron bir araçtır, bir din değil. Kullanıcı belirli bir yanıtı bekleyerek orada durduğunda — bir giriş, bir bakiye kontrolü, bir arama sonucu — senkron tutun. Kullanıcının az önce kaydettiği satırı görmeyi beklediği kendi yazdığını okuma (read-your-own-writes) akışları için senkron tutun. Ve bir olay veri yolunun işletme yükü ekleyip size hiçbir şey kazandırmadığı gerçekten basit CRUD işlemleri için senkron tutun. En sık gördüğüm başarısızlık biçimi, olay güdümlü tasarımın çok az olması değildir — ekiplerin "kullanıcı kaydete tıkladı" komutunu Kafka üzerinden itip buna mimari demesidir.
Pazartesi nereden başlamalı
Sistemi yeniden yazmayın. Sıkıntı yaratan tek bir senkron dağıtım bulun — genellikle bir dizi yan etki tetikleyen bir sipariş ya da bir kayıt — ve zorunlu olmayan tüketicileri bir olaya bağlayarak serbest bırakın. Ödemeyi senkron yapın; OrderPlaced yayımlayın ve e-posta, sadakat ve analitiğin asenkron olarak tepki vermesine izin verin. Veritabanı işlemi (commit) başarılı olup aracı (broker) çağrısı başarısız olduğunda asla bir olay kaybetmemek için giden kutusu desenine (outbox pattern) başvurun. İyi seçilmiş tek bir dikiş, ekibinize asenkron hakkında herhangi bir diyagramdan daha fazlasını öğretecektir.
Bir sonraki uç noktanızdan önce sorulmaya değer soru: çağıran tarafın bu yanıta gerçekten şimdi mi ihtiyacı var, yoksa onu yalnızca alışkanlıktan mı bekletiyoruz?