Bir önceki dersimize microservice ve monolitik uygulamaları karşılaştırarak mikroservis mimarisine giriş yapmıştık. Bu ikinci mikroservis dersimizde miroservis mimarisinin temelleri üzerinde duracağız.
Logical architecture ve physical architecture
İlk başlarken mikroservisleri inşa etmek için herhangi bir özel teknoloji kullanmak gerekmez örneğin, Docker container oluşturmak bir mikroservis için gerekli öncelik değildir. Bazı mikroservisler sade işleri yapabilir. Mikroservisler bir “logical architecture” yapılardır.
Physical architecture , logical architecture yapılarının ihtiyaç duyduğu ürünleri servisleri veya ihtiyaçları karşılayan fiziksel element ve arayüzlerden oluşmaktadır. Logical architecture her zaman fiziksel architecture içinde bire bir eşleşme gerektirmeyecektir.
Bununla birlikte belirli bir mikroservis veya Bounded Context(BC) sahip olabilirsin, bu daima tek bir mikroservise sahip olmayabilirsin. Bir docker conteinerı çinde birden fazla mikroservis eklenip container oluşturulabilir. Bunun ile birlikte mikroservis veya Bounded Context tasarımının fiziksel bir mimarideki yapı ile çakışabilir. Bundan dolayı mikroservis veya Bounded Context bağımsız kod yapısına bağımsız durumlara versiyonlamaya yayınlamaya ve ölçeklemeye sahip olmalıdır.
Şekil 1: Farklı fiziksel servislerde microservis mimarisi
Burada catalog mikroservisi farklı servislerden oluşuyor. Yukarıda görüldüğü gibi “Web Api Service” ve “Search Service” farklı tür altyapılardan oluşabilir. Örneğin bir Web API olabileceği gibi bir Soap service de olabilir.
Yukarıdaki örnekte iki farklı servisin tek bir database erişmesi gerekmektedir. Buradaki servisleri fiziksel implementasyonunda da görüldüğü gibi farklı servisleri fiziksel implementasyonu bu servisleri istediğimiz şekilde ölçekleyebileceğimizi onlara ayıracağımız kaynakları arttırıp azaltabileceğimizi ihtiyaç oranında kaynak ayırabileceğimizi bilmemiz gerekiyor.
Kısacası yukarıda da anlaşılacağı gibi mikroservis logical architecture her zaman physical architecture ile çakışmaz. Burada makalelerde genel itibari microservislerden bahsettiğimizde bir business mikroservisinden bahsediyor olacağız ve bu “logical microservice architecture” bir veya daha fazla physical service de ayağa kaldırılabilir.
Dağıtık Mimarilerde Data Yönetim Çözümleri
1. Bounded Context: Bir mimari tasarlarken domain driven design geliştirme yönteminde ilk yapılacak adım domainleri ve Bounded Context belirlemedir. Bu durum bir mikroservisi belirlerken karşılaşılacak ilk problemlerder biridir.Her mikroservisin kendi içinde bağımsız bir yapıda kurgulaması gerekebilir fakat mikrosersiler bir uygulamanın bir parçası da olabilir. Örneğin; bir E-Ticaret yazılımını baz alırsak “Ürün,”,”Sipariş”,”Ayarlar” gibi mikroservisler olabilir. Bu durumda yoğunlaşılması gereken diğer bir konu ise mikroservislerin içindeki domain ve bu domainlerin ilişkili datalarını belirlemektir. Burada en önemli olan konulardan birtanesi de aynı uygulama içerisinde bağımsız veri yapıları oluşturmaktır. Bu Context ler bağımsız olarak geliştirilebilir ve yönetilebilir durumda olmalıdır. Bir contextin içindeki domainler farklı olmalıdır fakat farklı domainler içindeki entity ler farklı isim ile iletişimde olabilir.Örneğin bir e ticaret sisteminde Satıcı olan biri aynı zamanda o e ticaret sisteminde alıcı da olabileceği için Sipariş mikroservisinde “User” olarak adlandıırlırken “Ürün” mikroservisinde “Seller” olarak adlandırılabilirler. Bu yöntem ile farklı uygulamadaki business mikroservisindeki contextleri arasında ve mikroservisdeki domain modellerinin arasındaki tutarlılığı ayarlamak için kullanılır.
2. Data Getirme: Bazı durumlarda çekeceğimiz ve sorgulayacağımız bilgi bir mikroservisde yer alıyor olacaktır. Fakat bazen uygulamanın etkiliğini arttırmak için birkaç mikroserviste sorgulama yapabilmekteyiz. Örneğin; bir e ticaret platformunda 3 adet mikroservis olduğunu hayal edin bu mikrosevisler “basket, product, customer ve checkout” olsun. Bir müşterinin sepet bilgilerini çekmek için basket mikroservisine ihtiyaç duyuluyorken raporlamalar yapılacağı zaman müşterininin “ürün adı, sipariş durumu ve sipariş eden bilgilerini” almak için yukarında adını yazdığımız “customer, product, checkout vb” gibi mikroservislere gitmek gerekebilir. Peki bu data toplama işlemlerini yapmak için hangi yöntemler kullanılıyor ona bakalım.
· API GATEWAY: Mikroservis mimarilerinde farklı mikroservislere erişmede kullanılan Api Gateway prensibi data toplama işlemi içinde kullanılabilir. Bir mobil, masaüstü veya web uygulaması içerisinde microservis mimarisindeki bir datayı getirirken gateway kullanılabilir. Burada farklı microservislerdeki dataya erişmek için gateway pattern yöntemi ile gelen talep ilgili yerlere yönlendirilebilir. Fakat bu pattern’ı dikkatli kullanmak zorundasınız çünk bu durum sisteminizde bir karışıklığa sebep olabilir. Çünkü bu durum her mikroservisin bağımsız olabilmesi ihtimalini yok edebilir.
Şekil 1. Basit bir Api Gateway Örneği
Api gateway data toplamada kullanılması işlemi çok dikkatli kullanılması gereken bir mikroservis prensibidir. Çünkü bu mikrservisin bağımsız olması gerçeğine zarar verebilir. Buradaki mikroservisin bağımsızlığını arttırmak için birden çok mikroservisi yapılandırıken iş katmanının ihtiyacı olan mikroservisi yatay bir mimari ile belirleyip bağımsızlığı arttırmaktır.
· CQRS Yöntemini Okuma ve Yazma Tablosu ile Kullanma: Farklı mikroservislerden dataya erişmenin diğer bir yolu Materialized View Pattern kullanmaktır. Temel itibari Materialized View Pattern’ı açıklayacak olursak genede yazılımcılar bir datayı nasıl depolayacaklarını düşünürler bunu nasıl okuyacaklarını düşünmezler. Data okuma işlemine yoğunlaşan bir konsepttir bu prensip. Bu pattern ile bir clientin istediği datayı onun okuyabileceği formata dönüştürerek okuma sırasında ek maliyetleri ve farklı mikroservisler üzerinde data getirme problemini ortadan kaldırabilirsin. Bu materialized Viewe tabloları birden fazla mikroservisdeki datayı birleştirip sadece okuma yapmada kullanılmalıdır. Materialized View sadece kullanıcının sorgulayacağı dataya odaklanır ve o datasetinin üzerinde tutar.
Şekil 2. Örnek bir Materialized View Görünümü
Esas konumuza dönecek olursak materialized View gibi sadece read-only tablolarımız olabilir ve bu tablolar birçok tablodan gelen data kaynağının ihtiyaç duyulan alanlarını üzerinde tutar. Bu yöntem temel olarak tek bir datakaynağında verilerin join yapılıp alınmasından ziyade farklı mikroservislerde data kaynaklarını okuyarak bu dataların ihtiyaç duydukları sorguları kendi içinde Materialized view yapılmış tablolara dönüştürüp sadece buradan okuma sağlamaktır. Bu yöntem tabiki bir mikrservis mimarisinde bütün problemlerimize çözüm olmayacaktır fakat complex join ve farklı mikroservislerde data çekme problemlerimizi çözecektir. Command and Query Responsibility Segregation (CQRS) prensibini read/query tabloları ile birlikte kullanmak daha farklı işlemleri getirecektir. Burada en önemli konu eventual consisty sağlayarak farklı datakaynakları arasıda data bütünlüğünü sağlamaktır.
· “Cold Data” Kullanımı: Genelde birçok iş için developerlar “hot data” kullanarak tüm bilgileri canlı veritabanından çekmeye çalışırlar. Özellikle raporlamalar için soğuk data kullanarak özellikle raporlamalar sıcak datanın olduğu işlem veritabanları etkilenmemiş olacaktır. Cold Database’ler sadece sorgulama için kullanılır. Eğer yaptığınız mikroservis mimarisi birçok mikroservisden bilgi çekip karşınıza getiriyor ise yapılan sistem kötü bir sistem olduğuna işaret edebilir. Bundan dolayı mikroservisin bağımsızlığını sağlamak için bazı durumlarda Cold Databse yöntemi kullanılabilir.
3. Mikroservisler Arasında Tutarlılık: Bir mikroservisden bir datayı okuma veya o mikroservisin içerdiği işi yapma sadece bir mikrorservise ulaşmada kullanılan iyi bir yöntemdir. Fakat bununla birlikte birden çok mikroservisde birbiri ile ilintili işleri yapma veya birbirini ilgilendiren bilgileri güncelleme işlemine gelince burada karşımıza bütük bir problem çıkacaktır. Örneğin bir muhasebe yazılımında “Order” Mikroservisi sipariş işlemlerini içeren iş kurallarını yapsın. Yine aynı zamanda “Case Account” Mikroservisi ise kasa hareketlerini yapan ve bunun ile ilgili dataya erişimi olan bir mikroservis olduğunu hayal edin. Burada her sipariş olduğunda kasa ile ilgili mikroservisde de bir hareket ve datada bir değişim olması gerekmektedir. Veya tam tersine bir hareket durumunda o kasadan o hareket silinince o siparişinde iptal edilmesi gerekmektedir. İşte bu durumda bu tarz hareketlerin farklı mikroservislerdeki diğer iş durumunu ve datayı etkileme durumu olmaktadır. Bundan dolayı farklı mikroservisler arasında bir tutarlılık olması gerekmektedir. Bu durumda Order mikroservisi veya Case Account mikroservisi biririni ilgilendiren datalara direk ulaşmak yerine eventual consistency prensini ile datayı ilgili mikroservise göndermesi ve diğer tüm tetiklemelerin ve data değişiminin o mikroservis üzerinde yapılması sağlanmalıdır
Yukarıdaki örnekte gördüğünüz gibi order mikroservisi kendi datasını kendi üzerinde tutuyor ve kendi business katmanından sonra datayı kaydediyor. Eğer işlem başarılı ise Eventual Consistency prensibine göre talebi Case Account Mikroservisine gönderiyor. Burada kesinlikle datayı direk Case actiona direk kaydetmiyor. Eğer bir mikroservis bağımsız ise kendine ait iş kuralları ve datası vardır. Bu durumda datayı bir mikroservise gönderdikten sonra tüm sorumluluğu o mikroservise vermek gerekmektedir.
Bundan dolayı bir çok mikroservis yüksek ölçeklenebilirlik ve güçlü tutarlılık ister. Yazılımcılar bu güçlü tutarlılığı sağlamak için çeşitli yöntemler kullanarak uygulamalarını ayakta tutmak isterler. Bu da genelde çoğu mikroservis tabanlı uygulamalarda geçerli olur.
Bununla birlikte ACID veya 2PC mikroservis mimarisi prensibine karşı prensiplerdir fakat bazı NOSQL databaselerin 2PC Transactionları desteklemediğini yani bir işlem başarısız olunca diğer işlemler de geri alınamayacağı için data bütünlüğünü sağlamada problem olacaktır. Bununla birlikte data bütünlüğünü sağlamak da çok önemlidir. Bundan dolayı pekçok microservis mimarisisinde data bütünlüğünü sağlamak için event-driven comminication ve bir publis ve subscribe sistemi kullanmak gerekmektedir.
4. Microservis Arasında Etkileşim: Birden çok mikroservis arasında iletişimi sağlamak için belirli yöntemler vardır Bunlar http, REST, AMQP vs.Burada iki mikroservis arasında etkileşimin nasıl olacağını ihtiyaçlarının belirleyecektir. Örneğin bir işlemin farklı mikroservisler arasında bağımlılık düzeyin nedir veya hata olduğunda ne olmalı gibi önemli sorulara cevap aramalı sonra mikroservisler arasında iletişim belirlenmelidir.
Mikroservis tabanlı mikmarilerde pekçok server uygulama ve database ile çalıştığı için data bütünlüğünde hata olacaktır. Sistemin bir bölümümnde belirli bir süreli veya uzun kesintiler olma riskini göz önüne almak ve bu dağıtık mimariyi çalıştırırken bu riskleri göz önüne almak gerekmektedir.
Comentarios