Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

Microservice Mimarilerde Saga Pattern İle Transaction Yönetimi

Merhaba,

Biliyorsunuz ki, yazılımsal operasyonlarda belirli senaryolarla baş edebilmek için tecrübevi birikim olarak yazılımcılar tarafından tatiksel tanımlanmış design pattern stratejilerinden istifade etmekteyiz. Design pattern uyarlılığı microservice yapılanmalarında da varlığını göstermekte ve yaşanılan problemlerde çözüm olarak imdadımıza yetişmektedir. Bu içeriğimizde, microservice yapılanmalarında en kritik konulardan birisi olan distributed transaction senaryolarında servisler arası veri tutarlılığını sağlamamıza imkan veren Saga Pattern üzerine konuşuyor olacağız. Tabi makale seyri boyunca acele etmeyecek ve Saga Pattern nedir? Ne şekilde uygulanmaktadır? gibi soruları cevaplandırmaya başlamadan önce pergeli doğru noktaya koyarak transaction kavramı üzerinden sınırlarımızı çizmeye başlayacağız. Ardından distributed transaction kavramını anlayabilmek için öncelikle servis başına veritabanı prensibi üzerinde istişarede bulunacağız. Devamında ise verisel açıdan yapılan değişikliklerin veritabanları üzerinde hangi prensipler doğrultusunda uygulanacağını(ACID) açtıktan sonra artık neden Saga Pattern’a ihtiyacımız olduğunu netleştirmiş olacağız. Nihayetinde asıl konumuz olan Saga Pattern’ın detaylarına girecek ve kavramsal olarak nelerden oluştuğunu inceledikten sonra teknik açıdan anotomisini inceleyeceğiz. Yani anlayacağınız, uzun ama bir o kadar da öğretici bir içerik bizi bekliyor olacak 🙂 Eee o zaman hiç vakit kaybetmeden buyrun başlayalım…

Bu Makalenin Konusu Nedir?

Her şeyden önce bu içerikte neyin anlatılmaya çalışıldığını anlayarak başlayalım. Biliyorsunuz ki, microservice mimarilerinde ideal olarak her bir servisin kendine ait bir veritabanı olması gerekmektedir.(Eğer bilmiyorsanız artık öğrenmiş oldunuz 🙂 Gerçi aceleci davranmaya gerek yok. Bu ideal kararı birazdan ayrı bir başlık altında eğrisi ve doğrusuyla değerlendiriyor olacağız.) İşte bu birden fazla servise dağıtılmış veritabanı sistemi distributed transaction olarak nitelendirilmektedir. (Keza bu kavramı da ayrı başlık altında daha da detaylandırıyor olacağız.) Her servisin kendine ait bir veritabanı olması dolayısıyla bu veritabanların arasında yapılan işe/hizmete göre bütünsel bir veri tutarlılığının sağlanmasını gerektirmektedir. Ee haliyle bu durumda gayet doğaldır, öyle değil mi? Yani bir yazılım projesinde birden fazla veritabanı kullanılıyorsa eğer bu veritabanlarındaki verilerin bütünsel açıdan tutarlı olmasını beklemek işin doğasında vardır.

Bu durumu şöyle bir örnekle zihinlerimizde tahayyül edelim; farz edelim ki bir e-ticaret yazılımı geliştiriyoruz. Bu yazılımın sipariş alma işlemlerini ‘Order’, siparişten sonra stok işlemlerini ‘Stock’ ve son olarak da ödeme işlemlerini ‘Payment’ servislerinde yaptığımızı düşünelim. Tabi ki de tüm bu servisin yukarı paragraflarda hafiften çıtlattığımız gibi kendilerine ait veritabanları olduğunu düşünelim ve senaryotik açıdan işlemlerin şu şekilde seyr ettiğini farz edelim :

Kullanıcı herhangi bir ürüne dair sipariş verdiğinde ‘Order’ servisi bu işlemi gerçekleştirecek ve kendi veritabanına ekleyecektir. ‘Payment’ servisi ise ödemeyi sağlayacak ve ödeme başarılıysa ‘Stock’ servisinde ki ilgili ürüne karşılık gelen stok miktarını düşürecektir.

Şimdi bu işlem seyrinde, ‘Order’ servisi gelen siparişi oluşturduktan sonra ‘Payment’ servisi o siparişe dair ödemeyi başarılı gerçekleştirirse eğer ‘Stock’ servisinde siparişteki ilgili ürüne dair stok adedinin düşürülmesi gerekmektedir. Aksi taktirde bir tutarsızlık meydana gelecektir. Düşünsenize, sipariş verilip ödeme yapıldıktan sonra hala stok miktarı aynı kalmaktadır. Bu durumun yazılımdaki verisel istatistiklere ve o yazılımı kullanan işletmeye verdiği zararı düşünün!

İşte bizim birden fazla serviste birden fazla veritabanıyla çalışılması(distributed transaction) durumlarında veri tutarlılığından kastımız budur. Haliyle bu içeriğimizde distributed transaction senaryolarında bu bahsedilen veri tutarlılığının sağlanabilmesi için önerilen çözümlerden biri olan Saga pattern’ınını inceliyor olacağız.

Transaction, Distributed Transaction ve Compensable Transactions Nedir?

Evet, şimdi teorik olarak bu makaleyi daha da iyi anlayabilmek için gerekli olan temel kavramları inceleyebiliriz. İlk olarak transaction kavramına değinerek başlayacağız.

  • Transaction
    Transaction, bilindiği üzere veritabanı üzerinde yapılan tüm işlemlere verilen genel isimdir. Bu duruma genellikle banka sistemleri üzerinden örneklendirme yapılmakla beraber ben deniz sizlerin konuya vakıf olduğunuzu düşünerek boğmamaksızın detaylandırmayı es geçmekteyim. Yine de transaction’a dair herhangi bir fikri olmayanlar tee zamanında yazdığım Transact Sql-Transaction başlıklı makalemi okuyabilirler. Aradan yıllar geçmesine rağmen transaction’a dair pek bişey değişmemiş diyebilmekteyiz.
  • Distributed Transaction
    Distributed Transaction’a gelirsek eğer bu bizim için önemlidir. Birden fazla farklı veritabanının bir bütün olarak çalıştığı durumu ifade eden bu terim adı üzerinde dağıtılmış veritabanı sistemleri için kullanılmaktadır. Genellikle microservice gibi yaklaşımlarda her bir servisin kendi veritabanını taşıması distributed transaction olarak nitelendirilir.
  • Compensable Transaction
    Compensable Transaction ise, bir transaction’ın yapmış olduğu işlemin tersini almaktır. Yani commit edilen bir işlemin geriye dönüklüğü bu saatten sonra ancak telafi ile mümkündür. İşte bu geri dönük telafi işlemine compensable transactions denmektedir. Misal olarak; ‘A’ servisi yapmış olduğu bir işlemi ‘B’ servisindeki duruma göre iptal etmek zorundaysa ‘A’ servisi bunu ancak yapılan işin tam tersini alarak gerçekleştirebilmektedir. Örneğin, 100 değerine +10 eklendiyse, bu işlemin iptali -10 eklenmesidir. Bu kavramın teknik olarak Saga pattern’ın da çok kullanıldığını göreceksiniz.

    Microservice Mimarilerde Saga Pattern İle Transaction Yönetimi

    Örnek bir Compensable Transaction şeması.

    Yukarıdaki şema üzerinden compensable transaction’ı yorumlarsak eğer; görüldüğü üzere ‘customer’ yaptığı alışveriş neticesinde n liralık ödeme talimatını ‘issuing bank’a vermekte ve ilgili bankadan ‘acquiring bank’a belirtilen miktarda para gönderilmektedir. Haliyle ilk etapta ‘issuing bank’tan -n lira eksilirken akabinde herhangi bir sıkıntı söz konusu değilse ‘acquiring bank’a n lira + olarak yansıyacaktır. Eğer sıkıntı söz konusu olursa yapılan işlemler geri alınacak ve ‘issuing bank’tan alınan n lira + olarak geri yüklenecektir. Benzer mantıkta gönderilen para ‘merchant’a erişim gösteriyorsa aradaki tüm servislerin transaction’ları doğrulanacak aksi taktirde yaşanacak herhangi bir aksi durumda tüm servislerdeki transaction’lar da yapılan tüm işlemlerin tersi alınarak telafi sağlanmış olacaktır. İşte burada her olumsuz duruma istinaden tüm servislerdeki yapılan çalışmaların geri alınması compensable transaction’dır.
Microservice Yapılanmasında Veritabanları Nasıl Tasarlanmalıdır?

Şimdi sıra microservice yapılanmalarında tasarımsal açıdan veritabanlarını nasıl yapılandıracağımızı konuşmaya geldi. Bu sorunun cevabını doğru şekilde verebilmek Saga pattern’ının temel gereksiniminin anlaşılmasında yardımcı olacağı kanaatinde olduğumdan dolayı gelin detaylıca istişare eyleyelim.

Microservice yaklaşımında her bir servisin bağımsız olarak geliştirilebilmesi, deploy edilebilmesi ve ölçeklendirilebilmesi için kendine ait, özel ve direkt erişilebilir veritabanlarına ihtiyacı vardır. Tabi ki de birden fazla servis aynı veritabanını kullanabilir ama bu durum pek ideal değildir. Servisler kendilerine ait veritabanlarına sahip olarak esasında kendi aralarında gevşek bir bağımlılık sergileyebilme özelliği kazanabilmektedirler. Böylece her servis ihtiyacına uygun veritabanı seçebilme hüvviyetine sahip olacaktır. Örneğin; metin araması yapan bir servis Elasticsearch’ü kullanırken, bu metinlerle ilgili farklı bir işlev yapan başka bir servis NoSQL yaklaşımı olan MongoDB’yi kullanabilir.

Her bir servisin kendi veritabanını kullanmasının elbette ki dezavantajları da mevcuttur. Bunlardan en önemlisi diyebileceğimiz, veritabanları arasında verileri birleştirerek(join) sorgulamak ve bütünsel istatiksel sonuçlar üretebilmek oldukça zor ve zahmetlidir bir işlevdir.

Değişiklikler Veritabanlarına Nasıl Uygulanmalıdır?
(ACID Prensipleri)

Veritabanlarının nasıl tasarlanacağından sonra dağıtılmış veritabanlarında yapılan verisel değişikliklerin nasıl uygulanacağını da konuşmakta fayda vardır. Muhtemelen bu başlığı gördüğünüzde la hoca veritabanlarındaki değişikliği uygulamakta ne var la allahisen! alt tarafı insert, update, delete işte! diyenleriniz olacaktır. Haliyle işi gücü bırakıp gelip size bu değişikliklerin teknik olarak nasıl uygulanması gerektiğini anlatma gibi gereksiz bir vizyona sahip olduğumu düşünmenizi istemem 🙂 Burada veritabanlarına yapılacak verisel değişiklerin hangi “prensipler” çerçevesinde uygulanması gerektiği üzerine istişare eyliyor olacağız. Yani konumuz ilkeler 😉

Bir yazılımın dağıtılmış veritabanları üzerinde bulunduğu verisel herhangi bir müdahale neticesinde bu işlemin nasıl uygulanacağını belli başlı prensipler doğrultusunda değerlendirmekteyiz. Bu prensipler sayesinde veritabanları üzerinde veri tutarlılığına dair tatminkarlık seviyemizi ölçebilir ve çıkılan yolda aklın ne kadar ütüde kalması gerektiğine dair bir nebze karar verebiliriz.

Dağıtılmış veritabanlarında yapılan değişiklerin nasıl uygulanacağını ifade eden prensipler baş harflerinden meydana gelen ACID Prensipleri olarak nitelendirilmektedir. ACID Prensipleri; Atomicity, Consistency, Isolation ve Durability olmak üzere dört tanedir.

  • Atomicity
    Atomicity, veritabanları üzerinde yapılan değişiklik sürecinde tüm transaction’ların başarılı olması gerektiğini ifade eder. Yani bu prensip, servisler arasında yapılan bir verisel müdahele neticesinde tüm veritabanlarındaki transaction’ın başarılı bir şekilde neticelenmesini aksi taktirde herhangi birinde başarısızlık olursa tüm transaction’ların geri alınması gerektiğini savunur. İnternetten bir kaç makaleye göz atarsanız ya hep, ya hiç! sloganıyla tanınan bir prensip olduğunu göreceksiniz.
  • Consistency
    Consistency, verilerin tutarlı olması gerektiğini savunur. Yani servislerdeki veritabanları bütünsel açıdan anlamlı ve tutarlı olmalıdır. Misal olarak; ‘X’ servisindeki ‘a’ kaydına karşılık ‘Y’ servisinde ‘b’ kaydının olması durumunda rahat olabilirsiniz. Lakin ‘X’ servisinde herhangi bir karşılığı olmaksızın ‘Y’ servisinde bir verinin olması durumu söz konusu olursa bi nooluyo demenizde fayda var. Nihayetinde veritabanları arasındaki tutarsızlık netice olarak bütünsel açıdan istatistiki tutarsızlığa varacaktır. Haliyle consistency dağıtılmış veritabanları söz konusu olduğunda göz önünde tutulması gereken bir prensiptir.
  • Isolation
    Isolation ise transaction’ların kendi aralarındaki izalasyona odaklanmamızı öneren bir prensiptir. Yani tüm servislerdeki transaction’lar bir diğerinden bağımsızdır ve yapısal olarak ardışıl servislerde birindeki işlem bitmeksizin diğerinin başlamaması gerekmektedir. Başlıyorsa, uykunuzdan alıp o işe vermenizde fayda var 🙂
  • Durability
    Durability ise verilerin güvenli ortamda saklanmasını savunur. La hoca demesen gidip CD ya da diskette verileri saklayacaktık! dediğinizi duyar gibiyim. Evet, bu tepkinize katılıyorum. Bu biraz lüzumsuz bir ikaz olmuş olabilir. Amma velakin durability verilerin kararlı, dayanıklı ve sürekliliği garanti edilmiş bir ortamda (sabit disk gibi) saklanması gerektiğini söylüyor işte… Ben napiiim 🙂 Yine de kulağınıza küpe olsun şeklinde yorumlayıp, öyle in-memory vs. gibi gece uykunuzu kaçıracak noktalarda verileri tutmamanız gerektiğine dair kendinize bir ilke edinmenizde fayda olacaktır.
Saga Nedir?

Saga, farklı ve bağımsız servisler üzerinde birden fazla transaction’ın sistematik bir şekilde işlenerek veri tutarlılığının sağlanmasını ifade eden ve ilk olarak 1987 yılında akademik bir makalede(bknz : SAGAS) yer edinen bir design pattern’dır. Bu pattern’ın işlevsel mantığı ilk transaction dış bir etki ile(örneğin kullanıcı tarafından butona tıklama) tetiklendikten sonra, bir önceki servisteki transaction’ın başarılı olması durumuna göre bir sonraki servisteki transaction’ın tetiklenmesi ve bir silsile halinde bu şekilde diğer servisler üzerinde tetiklenmenin devam etmesi üzerinedir. Böylece geliştirilen proje her ne kadar microservice yaklaşımını benimsemiş olsa da yapılan bir operasyon neticesinde tüm servislerdeki datalar tutarlı bir şekilde işlenmiş olacaktır.

Tabi süreçte transaction’lardan herhangi birinde oluşabilecek bir hata veya iş mantığı gereği iptal edilmesi gereken bir adım söz konusu olursa tüm süreç iptal edilecek ve işlenen transaction’lar tüm servislerde geri alınacaktır(Compensable Transaction) Böylece Atomicity prensibi desteklenmiş olacaktır.

Saga, microservice’ler arasında doğru transaction yönetimi ve veri tutarlılığı sağlayan bir design pattern’dır.

Saga’nın uygulanması için teknik olarak Events/Choreography ve Command/Orchestration isminde iki farklı implemantasyon geliştirilmiştir. Şimdi gelin bu implemantasyonları teorik olarak detaylıca inceleyelim.

Saga – Events/Choreography Implemantasyonu

Microservice Mimarilerde Saga Pattern İle Transaction YönetimiBu implemantasyonda microservice’ler arası merkezi bir denetim ve haberleşme noktası olmaksızın birbirleriyle eventler aracılığıyla haberleşilmesi esastır. Yani servisler arası iletişimin asenkron olarak tasarlanması gerektiğini savunmaktadır.

Genellikle bu iletişimin message broker ile gerçekleştirilmesi tercih edilir. Ama bu senkron bir iletişiminde kesin olamayacağı anlamına gelmemekte sadece ideal olarak eventler sayesinde asenkron tercih edilmektedir.

Taktiksel olarak Choreography’u incelersek eğer, ilk serviste başlayan transaction işlevini bitirdikten sonra sonraki servise haber gönderebilmek için message broker üzerinden bir event fırlatacaktır. Ardından bu servisteki transaction işlevini bitirdikten sonra kendisinden sonraki servisi tetikleyebilmek için yine bir event fırlatacaktır. Ve bu süreç client’ın istediği işlem bitene kadar silsile halinde işlevdeki son servise kadar devam edecektir. Buradan anlayacağımız her bir servisin kendisinden sonraki servisin tetiklenip tetiklenmeyeceğine dair kararı verdiğini görmekteyiz. Her bir servis yapılan işlev neticesinde kendi sürecine bağlı bir şekilde başarılı ya da başarısız bir karar vermekte ve bu neticeye göre ya kendisinden sonraki servisteki transaction’ın başlamasını sağlayabilmekte ya da tüm transaction’ları geri alabilmektedir. Yani her bir servis bizzat karar verici konumundadır.

Choreography implemantasyonu, distributed transaction’a katılacak olan microservice sayısının 2 ile 4 arasında olduğu durumlarda tercih edilir. 4’ten fazla servis durumunda yazımızın devamında inceleyeceğimiz Orchestration implemantasyonunu uygulamak daha uygundur..

Choreography’de her bir servis kuyruğu dinler. Dinlediği event message türüne göre gelen bir message söz konusuysa gerekli işlemlerini gerçekleştirir ve sonuç olarak muhakkak durumu bildiren başarılı yahut başarısız bilgisini kuyruğa event olarak ekler. Ardından diğer servisler bu event’e göre ya işlevlerine devam edecektirler ya da tüm transaction’lar geri alınıp veri tutarlılığını sağlayacaktırlar.

Örnek olarak aşağıdaki görseli incelersek eğer bir e-ticaret uygulamasında Choreography implemantasyonuyla oluşturulan siparişi görmekteyiz.Microservice Mimarilerde Saga Pattern İle Transaction YönetimiBu uygulamada bir siparişi oluşturabilmek için;

  1. Order serviste alınan POST isteği neticesinde sipariş oluşturulur.
  2. Order events channel kuyruğuna ‘OrderCreated’ misali bir event gönderilir.
  3. Customer servisi ise Order events channel‘da ki ‘OrderCreated’ event’ına subscribe olmaktadır. Haliyle ilgili kuyruğa beklenen türde bir event gelirse Customer servis tetiklenecektir.
  4. Customer servis müşteriye dair gerekli tüm işlemleri yaptıktan sonra eğer işlemler başarılıysa ‘OrderSucceded’ isminde yok eğer değilse ‘CreditLimitExceeded’ isminde Customer evens channel kuyruğuna bir event yayar.
  5. Haliyle ilgili kuyruğu dinleyen(subscribe) Order servis gelen event’ın türüne göre ya siparişi onaylar ya da reddeder.

Görüldüğü üzere servisler arası uçtan uca(point to point) bir iletişim olmadığı için coupling azalacaktır. Ayrıca transaction yönetimi merkezi olmadığı için performance bottleneck azalacaktır..

Ayrıca Choreography yöntemi, sorumlulukları Saga katılımcı servisleri arasında dağıttığından dolayı tek bir hata noktası olmayacaktır. Bundan dolayı da ekstra bakım gerekmemektedir.

Şimdi Choreography implemantasyonuna daha efektif bir örnek vererek ilerleyelim. Örneğimiz yine bir e-ticaret yazılımının sipariş sürecindeki detaylarını yansıtacaktır;
Microservice Mimarilerde Saga Pattern İle Transaction Yönetimi

  • 1. Adım
    Kullanıcıdan gelen yeni sipariş isteği neticesinde Order Service bu siparişi durum bilgisi Suspend olacak şekilde kaydeder. Ardından ödeme işlemlerinin gerçekleştirilebilmesi için ORDER_CREATED_EVENT isimli event’i fırlatır.
  • 2. Adım
    ORDER_CREATED_EVENT‘ine subscribe olan Payment Service gerekli ödeme işlemlerini gerçekleştirir ve artık alınan ürünlerin stok bilgilerini güncellemek için BILLED_ORDER_EVENT isimli event’i fırlatır.
  • 3. Adım
    BILLED_ORDER_EVENT‘ine subscribe olan Stock Service bu event fırlatıldığında devreye girer ve gerekli stok ayarlamalarını gerçekleştirir. Artık herhangi bir problem olmadığı taktirde ürünlerin teslimatı için ORDER_PREPARED_EVENT isimli event’i fırlatır.
  • 4. Adım
    ORDER_PREPARED_EVENT‘ine subscribe olan Order Service artık bu siparişin başarıyla tamamlandığına kanaat getirmiş olarak siparişin durumunu Completed olarak günceller.

Yukarıdaki adımlardan herhangi bir durumda hata meydana geldiği taktirde tüm işlemlerin geri alınması gerekmektedir. İşte bu durumda aşağıdaki senaryo devreye girecektir;

Microservice Mimarilerde Saga Pattern İle Transaction YönetimiDistributed transaction süreçlerinde bir işlemi geri almak demek esasında o işlemi telafi etmek ya da tam tersini uygulamak için başka bir işlem yapılması demektir(Compensable Transaction) Dolayısıyla yandaki görselden yola çıkarak üstteki işlem akışının yetersiz stok miktarından dolayı Stock Service‘de başarısızlığa uğradığını varsayarak sürecin nasıl işlediğini simüle edelim…

  • 1. Adım
    Ödeme işleminden sonra Stock Service‘te yeterli stok olmadığı anlaşıldığı taktirde PRODUCT_OUT_OF_STOCK_EVENT isimli event fırlatılır.
  • 2. Adım
    PRODUCT_OUT_OF_STOCK_EVENT‘ine subscribe olan Payment Service ve Order Service‘lerde önceki yapılan tüm işlemlerin tersi uygulanır. Nedir bu tersine işlemler diye sorarsanız eğer; Payment Service‘te alınan ödeme kullanıcıya tekrar geri yapılır ve Order Service‘te ise sipariş durumu Fail olarak güncellenir.
Saga – Events/Choreography Implemantasyonunun Dezavantajları Nelerdir?
  • Hangi servisin hangi kuyruğu dinlediğini takip etmek zorlaşır. Yeni servis eklemek zor ve kafa karıştırıcı olabilmektedir.
  • Birbirlerinin kuyruklarını tükettikleri için servisler arası döngüsel bir bağımlılık riski vardır.
  • Bir işlemi simüle etmek için tüm servislerin çalışıyor olması gerektiğinden entegrasyon testi zordur.
Saga – Command/Orchestration Implemantasyonu

Microservice Mimarilerde Saga Pattern İle Transaction YönetimiBu yaklaşımda servisler arası distributed transaction merkezi bir denetleyici ile koordine edilir. Bu denetleyiciye Saga State Machine ya da bir başka isim olarak Saga Orchestrator denmektedir. Saga Orchestrator, servisler arasındaki tüm işlemleri yönetir ve olaylara göre hangi işlemin gerçekleştirileceğini söyler.

Saga Orchestrator, diğer ismi olan Saga State Machine adından da anlaşıldığı üzere her kullanıcıdan gelen isteğe dair uygulama state’ini(durum) tutmakta, yorumlamakta ve gerektiğinde telafi edici işlemleri uygulamaktadır.
Microservice Mimarilerde Saga Pattern İle Transaction YönetimiMisal olarak yanda şematize edilmiş e-ticaret senaryosunu ele alırsak eğer;

  • Order Service sipariş isteğini alır ve durumunu Suspend olarak kaydeder. Ardından bu siparişe dair geri kalan işlemleri başlatmak için Saga Orchestrator‘a ORDER_CREATED türünden komut göndererek sipariş oluşturma transaction’ını başlatır.
  • Saga Orchestrator, EXECUTE_PAYMENT komutunu Payment Service‘e gönderir. İlgili servis ödeme alındığına dair başarılı ya da başarısız bilgiyi tekrar Saga Orchestrator‘a döndürür.
  • Saga Orchestrator, UPDATE_STOCK türünden komutu Stock Service‘e gönderir ve ilgili servis stok bilgisinin güncellenmesini gerçekleştirir. Yine nihai durum başarılı ya da başarısız olarak orchestrator’a döndürülür.
  • Orchestrator, ORDER_DELIVER komutunu Delivery Service‘e gönderir ve ilgili servis siparişin kargolandığı bilgisini başarılı yahut başarısız olarak döndürür.
  • Ve en nihayetinde sipariş durumu Completed olarak güncellenir.

Saga Orchestration implemantasyonunda Saga Choreography’de olduğu gibi asynchronous messaging pattern tercih edilmektedir.

Yukarıdaki senaryoda servislerden herhangi birinde olası bir hata meydana geldiği taktirde aşağıdaki gibi hareket edilmelidir. Bu örnekte hata ‘Stock Service’ üzerinden misallendirilmektedir;
Microservice Mimarilerde Saga Pattern İle Transaction Yönetimi

  • Stock Service‘de sipariş edilen ürün adedi stok miktarından fazla ise orchestrator’a OUT_OF_STOCK komutu gönderilmektedir.
  • Ardından orchestrator işlem sürecinde başarısızlık olduğu bilgisini alıp rollback işlemlerini başlatır(Compensable Transaction)

Her işlem için Saga üzerinde state bilgisi tutmak hangi adımda süreci yanlış yönettiğinizi görmeyi kolaylaştıracaktır.

Orchestration implemantasyonunun faydalarına gelirsek eğer;

  • Birçok servisin bulunduğu ve zaman içinde servislerin eklendiği karmaşık iş akışları için idealdir. Burada alt eşik 4 adet servistir. 4’ün üzerinde servis söz konusuysa eğer orchestration implemantasyonu tercih edilir.
  • Her servisin ve bu servislerin faaliyetlerinin üzerinde merkezi kontrol sağlar.
  • Orchestration implemantasyonu, tek taraflı olarak Saga katılımcılarına(servisler) bağlı olduğundan dolayı döngüsel bağımlılıklar söz konusu değildir.
  • Her bir servisin diğer servisle ilgili bilmesi gereken herhangi bir şeye ihtiyacı yoktur! Haliyle böylece Separation of Concerns söz konusudur.
  • Uygulaması ve test etmesi choreography implemantasyonuna nazaran daha kolaydır.
  • Yapılan işler doğrusal kalacağından dolayı geri alma yahut telafi yönetimleri daha kolaydır.

Orchestration implemantasyonunun tek dezavantajı tüm iş akışının yönetiminin Saga Orchestrator tarafından gerçekleştiriliyor olmasıdır diyebiliriz.

Nihai Olarak Saga

Artık içeriğimizi noktalamadan önce Saga’ya dair nihai olarak yorumlarımızı yaparak genel mahiyette fikrimizi ortaya koyalım..

  • Görüldüğü üzere Saga’da ister choreography olsun isterse de orchestration olsun hangi implemantasyon kullanılıyorsa kullanılsın servis sayısı nicelik olarak arttıkça karmaşıklık artmaktadır.
  • Saga’da hata ayıklama(debugging) oldukça zor bir operasyondur.
  • Saga’da ki servislerin local veritabanlarında yapılan herhangi bir değişiklik geri alınamaz!
  • Bir Saga, bir başka Saga’nın yaptığı değişiklikleri okumadan veri işliyorsa Kayıp Güncellemeler söz konusu olabilir.
  • Ya da bir servis güncellemeleri henüz tamamlamadan bir başka servis tarafından yapılan güncellemeleri okuduğunda Kirli Okumalar söz konusu olabilmektedir.
  • Hatta servislerin data okumaları arasında bir veri güncellemesi meydana geldiğinde farklı verilerin okunup Bulanık Okumalara mahal verilebilmektedir.

İşte bu ve bunlara benzer durumlardan dolayı Saga pattern’ının kullanımı net özen gerektirmektedir.

Saga Orchestrator, subscribe olan tüm servisleri çağırabilir ancak servisler orchestrator’ü çağıramaz, çağırmamalıdır!

Evet.. Konuyu teorik olarak incelediğimiz bir içeriğimizin daha sonuna gelmiş bulunuyoruz. Bundan sonraki içeriklerimizde bu teorinin üzerine sırasıyla choreography ve orchestration implemantasyonlarına dair pratiksel detaylar barındıran esas operasyonel içeriklerimizi klavyeye alıyor olacağız. Dolayısıyla sizler bu makaleyi okurken ben deniz de sonraki makalelerin altyapılarını atmaya gidiyor, kolaylıklar diliyorum 🙂

Okuduğunuz ve eşlik ettiğiniz için teşekkür ederim…

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Kaynakça

https://microservices.io/patterns/data/saga.html
https://medium.com/devopsturkiye/microservice-mimarilerde-transaction-y%C3%B6netimi-nas%C4%B1l-yap%C4%B1l%C4%B1r-228317e248ed
https://docs.microsoft.com/tr-tr/azure/architecture/reference-architectures/saga/saga
https://sefikcankanber.medium.com/saga-pattern-nedir-e4a447bef361

Bunlar da hoşunuza gidebilir...

5 Cevaplar

  1. çok başarılı makale olmuş. eline sağlık

  2. Yunus dedi ki:

    Mükemmel anlatım . Çok faydalı bir makale eline sağlık .

  3. freelance developer dedi ki:

    güzel anlatım teşekkürler

  1. 15 Ağustos 2021

    […] önceki Microservice Mimarilerde Saga Pattern İle Transaction Yönetimi başlıklı makalemizde Saga pattern üzerine detaylıca teorik incelemede bulunmuştuk. Bu […]

  2. 25 Temmuz 2022

    […] bu servisin de yaptığı tüm işlemler bütünsel tutarlılık için geri alınmalıdır(Bknz : Compensable Transaction). Ama bu ne kadar doğru olacaktır? Nihayetinde distributed bir mimaride bazen servislerin geçici […]

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir