Ey Habr!
Hakkındaki kitabı takip etmenizi hatırlatırız.
Şimdilik topluluk bu güçlü aracın sınırlarını yeni öğreniyor. Yakın zamanda çevirisini size tanıtmak istediğimiz bir makale yayınlandı. Yazar, kendi deneyiminden yola çıkarak Kafka Akışlarını dağıtılmış bir veri deposuna nasıl dönüştüreceğini anlatıyor. Okumanın tadını çıkar!
Apache kütüphanesi
Bu yazımda firmamızın bulut uygulama güvenliğine yönelik bir ürün geliştirirken bu fırsatı nasıl karlı bir şekilde kullanmayı başardığını anlatacağım. Kafka Streams'i kullanarak, her biri sistemdeki nesnelerin durumu hakkında hataya dayanıklı ve yüksek düzeyde kullanılabilir güvenilir bilgi kaynağı olarak hizmet veren paylaşılan durum mikro hizmetleri oluşturduk. Bizim için bu, hem güvenilirlik hem de destek kolaylığı açısından ileriye doğru atılmış bir adımdır.
Nesnelerinizin resmi durumunu desteklemek için tek bir merkezi veritabanı kullanmanıza olanak tanıyan alternatif bir yaklaşımla ilgileniyorsanız, okuyun, ilginç olacaktır...
Neden paylaşılan durumla çalışma şeklimizi değiştirme zamanının geldiğini düşündük?
Temsilci raporlarına dayanarak çeşitli nesnelerin durumunu korumamız gerekiyordu (örneğin: site saldırı altında mıydı)? Kafka Streams'e geçmeden önce durum yönetimi için genellikle tek bir merkezi veritabanına (+ hizmet API'sine) güveniyorduk. Bu yaklaşımın dezavantajları vardır:
Şekil 1: Geçiş öncesinde görülen tipik bir bölünmüş durum senaryosu
Kafka ve Kafka Akışları: aracılar görüşlerini API aracılığıyla iletir, güncellenmiş durum merkezi bir veritabanı aracılığıyla hesaplanır
Paylaşılan durum mikro hizmetleri oluşturmayı kolaylaştıran Kafka Streams ile tanışın
Yaklaşık bir yıl önce, bu sorunları çözmek için ortak durum senaryolarımızı derinlemesine incelemeye karar verdik. Hemen Kafka Akışlarını denemeye karar verdik; ne kadar ölçeklenebilir, yüksek düzeyde kullanılabilir ve hataya dayanıklı olduğunu ve akış işlevselliğinin ne kadar zengin olduğunu (durum bilgisi olanlar dahil dönüşümler) biliyoruz. Tam da ihtiyacımız olan şey, Kafka'daki mesajlaşma sisteminin ne kadar olgun ve güvenilir hale geldiğinden bahsetmiyorum bile.
Oluşturduğumuz durum bilgisi olan mikro hizmetlerin her biri, oldukça basit bir topolojiye sahip bir Kafka Streams örneğinin üzerine inşa edildi. 1) bir kaynaktan 2) kalıcı anahtar/değer deposuna sahip bir işlemciden 3) bir havuzdan oluşuyordu:
Şekil 2: Durum bilgisi olan mikro hizmetler için akış örneklerimizin varsayılan topolojisi. Burada planlama meta verilerini içeren bir havuzun da bulunduğunu unutmayın.
Bu yeni yaklaşımda, aracılar kaynak konuya beslenen mesajları oluşturur ve tüketiciler (örneğin bir posta bildirim hizmeti) havuz (çıkış konusu) aracılığıyla hesaplanan paylaşılan durumu alır.
Şekil 3: Paylaşılan mikro hizmetlere sahip bir senaryo için yeni örnek görev akışı: 1) aracı, Kafka kaynak konusuna ulaşan bir mesaj oluşturur; 2) paylaşılan duruma sahip bir mikro hizmet (Kafka Akışlarını kullanarak) bunu işler ve hesaplanan durumu son Kafka konusuna yazar; bundan sonra 3) tüketiciler yeni durumu kabul eder
Hey, bu yerleşik anahtar/değer deposu aslında çok kullanışlıdır!
Yukarıda belirtildiği gibi, paylaşılan durum topolojimiz bir anahtar/değer deposu içerir. Bunu kullanmak için birkaç seçenek bulduk ve bunlardan ikisi aşağıda açıklanmıştır.
Seçenek #1: Hesaplamalar için anahtar/değer deposu kullanın
İlk anahtar/değer depomuz hesaplamalar için ihtiyacımız olan yardımcı verileri içeriyordu. Örneğin bazı durumlarda ortak durum "çoğunluk oyu" ilkesine göre belirleniyordu. Depo, bazı nesnelerin durumuna ilişkin en son aracı raporlarının tümünü tutabilir. Daha sonra, bir temsilciden veya diğerinden yeni bir rapor aldığımızda, bunu kaydedebilir, depodaki aynı nesnenin durumu hakkında diğer tüm aracıların raporlarını alabilir ve hesaplamayı tekrarlayabilirdik.
Aşağıdaki Şekil 4, yeni mesajın işlenebilmesi için anahtar/değer deposunu işlemcinin işleme yöntemine nasıl maruz bıraktığımızı göstermektedir.
İllüstrasyon 4: İşlemcinin işleme yöntemi için anahtar/değer deposuna erişim açıyoruz (bundan sonra paylaşımlı durumla çalışan her betiğin yöntemi uygulaması gerekir) doProcess
)
Seçenek #2: Kafka Akışlarının Üstünde CRUD API Oluşturma
Temel görev akışımızı oluşturduktan sonra, paylaşılan durum mikro servislerimiz için RESTful CRUD API yazmaya başladık. Nesnelerin bir kısmının veya tamamının durumunu alabilmenin yanı sıra bir nesnenin durumunu ayarlayabilmeyi veya kaldırabilmeyi (arka uç desteği için kullanışlıdır) istedik.
Tüm Get State API'lerini desteklemek için, işleme sırasında durumu yeniden hesaplamamız gerektiğinde, bunu yerleşik bir anahtar/değer deposunda uzun süre sakladık. Bu durumda, aşağıdaki listede gösterildiği gibi, Kafka Streams'in tek bir örneğini kullanarak böyle bir API'yi uygulamak oldukça basit hale gelir:
Şekil 5: Bir nesnenin önceden hesaplanmış durumunu elde etmek için yerleşik anahtar/değer deposunu kullanma
Bir nesnenin durumunu API aracılığıyla güncellemenin uygulanması da kolaydır. Temel olarak yapmanız gereken tek şey bir Kafka yapımcısı oluşturmak ve onu yeni durumu içeren bir kayıt oluşturmak için kullanmaktır. Bu, API aracılığıyla oluşturulan tüm mesajların diğer üreticilerden (örn. aracılar) alınanlarla aynı şekilde işlenmesini sağlar.
Şekil 6: Kafka yapımcısını kullanarak bir nesnenin durumunu ayarlayabilirsiniz
Küçük komplikasyon: Kafka'nın birçok bölümü var
Daha sonra, senaryo başına bir paylaşılan durum mikro hizmetleri kümesi sağlayarak işlem yükünü dağıtmak ve kullanılabilirliği artırmak istedik. Kurulum çok kolay oldu: Tüm örnekleri aynı uygulama kimliği (ve aynı önyükleme sunucuları) altında çalışacak şekilde yapılandırdığımızda, geri kalan hemen hemen her şey otomatik olarak yapıldı. Ayrıca her kaynak konusunun birkaç bölümden oluşacağını da belirttik, böylece her bir örneğe bu bölümlerin bir alt kümesi atanabilir.
Ayrıca, örneğin bir arızadan sonra kurtarma durumunda bu kopyayı başka bir örneğe aktarmak için durum deposunun yedek bir kopyasını oluşturmanın yaygın bir uygulama olduğunu da belirteceğim. Kafka Akışlarındaki her durum deposu için, bir değişiklik günlüğüyle (yerel güncellemeleri izleyen) çoğaltılmış bir konu oluşturulur. Böylece Kafka devlet deposunu sürekli yedekliyor. Bu nedenle, bir veya başka bir Kafka Akışı örneğinin arızalanması durumunda, durum deposu, ilgili bölümlerin gideceği başka bir örneğe hızlı bir şekilde geri yüklenebilir. Testlerimiz, mağazada milyonlarca kayıt olsa bile bunun birkaç saniye içinde yapıldığını gösterdi.
Paylaşılan duruma sahip tek bir mikro hizmetten bir mikro hizmet kümesine geçiş, Get State API'yi uygulamak daha az önemsiz hale gelir. Yeni durumda, her mikro hizmetin durum deposu genel resmin yalnızca bir kısmını içerir (anahtarları belirli bir bölümle eşlenen nesneler). İhtiyacımız olan nesnenin durumunu hangi örneğin içerdiğini belirlememiz gerekiyordu ve bunu aşağıda gösterildiği gibi iş parçacığı meta verilerine dayanarak yaptık:
Şekil 7: Akış meta verilerini kullanarak, istenilen nesnenin durumunun hangi örnekten sorgulanacağını belirliyoruz; GET ALL API'sinde de benzer bir yaklaşım kullanıldı
Ana sonuçlar
Kafka Streams'teki durum depoları fiili olarak dağıtılmış bir veritabanı olarak hizmet verebilir,
- Kafka'da sürekli kopyalanıyor
- Böyle bir sistemin üzerine kolayca bir CRUD API oluşturulabilir
- Birden fazla bölümü yönetmek biraz daha karmaşıktır
- Yardımcı verileri depolamak için akış topolojisine bir veya daha fazla durum deposu eklemek de mümkündür. Bu seçenek aşağıdakiler için kullanılabilir:
- Akış işleme sırasında hesaplamalar için gereken verilerin uzun süreli depolanması
- Akış örneğinin bir sonraki hazırlığında faydalı olabilecek verilerin uzun süreli depolanması
- daha fazla...
Bunlar ve diğer avantajlar, Kafka Akışlarını bizimki gibi dağıtılmış bir sistemde küresel durumu korumaya çok uygun hale getiriyor. Kafka Streams'in üretimde çok güvenilir olduğu kanıtlandı (dağıtıldığından beri neredeyse hiç mesaj kaybı yaşamadık) ve yeteneklerinin burada bitmeyeceğinden eminiz!
Kaynak: habr.com