SAGA Pattern Nedir?
Transaction’lar uygulamalarımızın önemli birer parçasıdır. Eğer transaction’lar olmasaydı veri tutarlılığını sağlamamız imkansız olurdu.
Veri tutarlılığını sağlayan çözümlerden birisi daha önceki makalemde bahsettiğim 2PC Pattern’dir. Bu pattern’de tüm akışı yönettiğimiz genel transaction içinde ikinci bir işlemin çalışması için ilk işlemin başarıyla tamamlanmış olması gereklidir. Örnek vermek gerekirse, bir e-ticaret sitesindeki siparişin oluşturulma sürecini verebiliriz.
Ancak, Microservice mimarisinde çalışıyorsak bilindiği üzere her servisin kendi veritabanı vardır ve 2PC Pattern ile tüm sistemdeki veri tutarlılığını sağlamamız biraz zorlaşacaktır.
2PC Pattern ilgili service özelinde tek bir istek ile ACID prensiplerini yerine getirmeye çalışır. Veri tutarlılığının önemli olduğu yerlerde kullanılır. SAGA ise birbirini bekleyen sıralı işlemlerin olduğu yapılarda kullanılmalıdır. Her işlem bir sonraki işlemden önce tetiklenir ve veriler en sonunda tutarlı hale getirilir. (2PC Pattern ile ilgili yazdığım makale için bknz.)
Bir e-ticaret sisteminden örnek vermek gerekirse;
Microservice mimarisi ile çalıştığımız için tek transaction ile sipariş oluşturmamız, ödeme almamız ve stok güncelleme işlemlerini yönetmemiz pek mümkün değildir. Tüm bu akışı yönetmek için distributed bir transaction oluşturmamız gereklidir.
Tabi ki distributed transaction ile uygulama geliştirirken dikkate almamız gereken bazı durumlar vardır.
- Service’ler arasındaki veri tutarlılığı
- Olası hata durumlarındaki rollback senaryoları
Sistemi tasarlama aşamasında bu kararların alınması uzun vadede ciddi sorunların önüne geçecektir. Bu gibi durumlara çözüm getiren makalemin ana konusu Saga Pattern tam olarak da şimdiye kadar açıklamaya çalıştığım sorunlara/durumlara çözüm getirmeyi amaçlar.
Saga Pattern Nedir?
Saga Pattern ile oluşturulan sistemlerde gelen istek ile daha sonraki her adım, bir önceki adımın başarılı şekilde tamamlanması sonrasında tetiklenir. Herhangi bir failover durumunda işlemi geri alma veya bir düzeltme aksiyonu almayı sağlayan pattern’dir.
SAGA TÜRLERİ
Orchestration-Based Saga
Bu yaklaşımda tüm işlemleri yöneten bir Saga orchestrator’u vardır. Bu orchestrator subscribe olan tüm consumer’lara ne zaman ne yapacağını ileten bir consumer’dır. Örnek bir e-ticaret senaryosu üzerinden Orchestration yaklaşımını şematize etmek gerekirse;
- Order service’imiz pending durumunda siparişi oluşturur ve Orchestrator’a ORDER_CREATED bilgisini gönderir ve Orchestrator’umuz sipariş oluşturma transaction’ınını başlatır.
- Orchestrator EXECUTE_PAYMENT komutunu Payment service’ine gönderir ve Payment geriye ödeme alındığı ile ilgili bilgiyi döndürür.(Başarılı olduğu senaryolar için..)
- Orchestrator UPDATE_STOCK komutunu Stock service’ine gönderir ve stock service’i geriye ilgili ürünlerin stok bilgisinin güncellendiği ile ilgili bilgiyi döndürür.(Başarılı olduğu senaryolar için..)
- Orchestrator ORDER_DELIVER komutunu Shipment service’ine gönderir ve Shipment geriye siparişin kargolandı bilgisini döndürür.(Başarılı olduğu senaryolar için..)
Her durum için saga üzerinde state tutmak hangi adımda süreci yanlış yönettiğinizi görmeyi kolaylaştıracaktır.
Yukarıda açıklamaya çalıştığım durumlarda, Orchestrator’ümüz bir siparişin oluşturulması için gerekli akışın ne olduğunu bilir. Olası bir failover durumunda, işlemleri geri almak için subscribe olmuş tüm service’lere geri alma işlemini koordine etmekten sorumludur. Saga Orchestrator yaklaşımı ile State Pattern’i kullanmak iyi bir çözümdür. State Pattern’in uygulanması kolay ve test edilebilirliği basitleştirdiği için yerinde bir tercih olacaktır.
Akışımızda oluşacak bir hata durumunda failover sürecinden bahsetmek gerekirse;
- Stock service’i Orchestrator’a OUT_OF_STOCK bilgisini gönderir.
- Orchestrator işlemin başarısız olduğu bilgisini alıp rollback işlemini başlatır.
Saga Orchestrator abone olan tüm service’leri çağırırabilir ancak, subscribe olan servisler orchestrator’ü çağıramaz. Çağırmamalıdır!!!!!
Avantajları ve Dezavantajları
- Distributed transaction yönetimini merkezileştirir.
- Implemente etmek ve test etmek kolaydır.
- Rollback yönetimi basittir.
- Yeni step’ler eklendiğinde işlem karmaşıklığı cherography yaklaşımına göre daha az kompleksleşir.
- Birbirini bekleyen işlemleri bu yaklaşım ile yönetebilirsiniz.
- Fazladan bir service’i yönetmeniz gerektiği için sisteminizdeki infrastructure karmaşıklığı artacaktır.
Choreography-Based Saga
Bu yaklaşımda merkezi bir yönetici yoktur. Her servis işlemi tamamlar ve event fırlatır ve bir sonraki servis ilgili event’i consume edip sürecine devam eder.
- Order Service’i siparişi oluşturur ve Pending statüsünde ORDER_CREATED_EVENT’i fırlatır.
- Payment Service’i ORDER_CREATED_EVENT’i dinler ve ödeme işlemini gerçekleştirip BILLED_ORDER_EVENT’i fırlatır.
- Stock Service’i BILLED_ORDER_EVENT’i dinler ve stok güncellemesini yapar ve ORDER_PREPARED_EVENT’i fırlatır.
- Shipment service’i ORDER_PREPARED_EVENT’ini dinler ve kargo işlemlerini gerçekleştirir ve ORDER_DELIVERED_EVENT’ini fırlatır.
- Son olarak, Order service’i ORDER_DELIVERED_EVENT’i dinler ve siparişin durumunu tamamlandıya çeker.
Burada her adımda sipariş durumunu güncellememiz gerekiyorsa her adımda order service’ine ilgili event’leri dinleyen bir consumer ile sipariş durumunu güncelleyebiliriz.
Yukarıdaki akışta hata olması durumunda rollback işlemi için yeni event’ler fırlatmamız gerekir.
- Stock service’i PRODUCT_OUT_OF_STOCK_EVENT fırlatır.
- Order ve Payment service’i bu event’i dinler ve Payment service’i ödemeyi geri alır, order service’i order’ın statüsünü Failed’a çeker.
Avantajları ve Dezavantajları
- Basit, anlaşılması kolay ve event’i tetikleyen servisler birbirinden ayrı olduğu için var olan bir sisteme implemente etmek kolaydır.
- Süreciniz 2 ila 4 adım içeriyorsa çok uygun olabilir.
- Ancak, hangi servisin hangi event’leri dinlediğini takip etmek, akış kompleksleştikçe daha karışık hale gelebilir. Ayrıca servislerin birbirine subscribe olmaları gerektiğinden döngüsel bağımlılıklar olabilir.
- Son olarak, sistemi tam anlamıyla test etmek için tüm service’lerin çalışır durumda olması gerektiğinden test yapmak zor olacaktır.
Microservice mimarisinde distributed transaction yönetimi çözümlerinden biri olan Saga Pattern hakkında temel düzeyde bilgi vermeye çalıştım.
Faydalı olması dileğiyle,
İyi çalışmalar.