Software Architecture

Saga Desenini Ustalıkla Kullanmak: Mikroservislerde Dağıtık İşlemlerin Orkestrasyonu

Monolitik uygulamalar dünyasında veri tutarlılığını korumak basittir. Tek bir veritabanı işlemi, bir iş sürecinin tüm adımlarının başarılı olmasını veya hiçbirisinin olmamasını sağlar. Ancak mikroservis mimarisine geçiş yaptıkça bu sadelik kaybolur. Her hizmet kendi veritabanına sahiptir, bu da hizmet sınırları boyunca geleneksel ACID işlemlerini imkansız kılar. İşte tam da burada Saga Deseni, modern yazılım mimarları için vazgeçilmez bir araç haline gelir.

Problem: Dağıtık Veri Tutarlılığı

Bir iş süreci birden fazla hizmeti kapsadığında, örneğin Envanter Hizmeti, Ödeme Hizmeti ve Kargo Hizmeti'ni içeren bir e-ticaret sipariş akışında, dağıtık işlemler zorluğuyla karşı karşıyayız. Yüksek gecikme süresi, sıkı bağlanma ve tek bir başarısızlık noktası potansiyeli nedeniyle, birçok modern ortamda standart iki aşamalı commit (2PC) protokolünü kullanamayız. Bunun yerine, uzun süreli işlemlerin, her biri karşılık gelen bir tazmin edici eylemle yerel işlemler dizisi aracılığıyla tutarlılığını korumasına olanak tanıyan bir desenimize ihtiyacımız var.

Saga Deseni Nasıl Çalışır

Bir Saga, yerel işlemler dizisidir. Her yerel işlem veritabanını günceller ve sagadaki bir sonraki yerel işlemi tetiklemek için bir olay veya mesaj yayınlar. Bir adım başarısız olursa, saga önceki adımlar tarafından yapılan değişiklikleri geri almak için bir dizi tazmin edici işlemi yürütür. Sagaları uygulamak için iki temel yol vardır:

  1. Koreografi: Hizmetler, merkezi bir koordine edici olmadan olaylar aracılığıyla iletişim kurar.
  2. Orkestrasyon: Merkezi bir koordine edici, saga akışını yönetir.

Koreografi ve Orkestrasyon Arasındaki Fark

Koreografi küçük sistemler için daha basit olsa da, karmaşıklık arttıkça izlemesi ve hata ayıklaması zorlaşabilir. AWS Step Functions veya Temporal gibi bir koordine edici kullanan orkestrasyon, daha iyi görünürlük ve kontrol sağlar ancak dikkatli tasarlanmazsa yeni bir başarısızlık noktası oluşturur.

Pratik Kod Örneği: Koreografi Yaklaşımı

"Sipariş Oluşturma" süreci için koreografi tabanlı bir saga'nın basitleştirilmiş bir Node.js örneğine bakalım. Burada RabbitMQ veya Kafka gibi bir olay arabirimi kullanmayı varsayıyoruz.

// Adım 1: Sipariş Oluştur (Yerel İşlem)
async function handleOrderCreated(event) {
    try {
        // Envanteri yerel olarak ayır
        await inventoryService.reserve(itemIds, quantity);
        
        // Ödemeyi tetiklemek için olay yayınla
        eventBus.publish('ItemsReservedEvent', { orderId: event.orderId });
    } catch (error) {
        // Tazmin: Ayırma başarısız olursa, sipariş iptalini bildir
        eventBus.publish('OrderFailedEvent', { orderId: event.orderId });
    }
}

// Adım 2: Ödemeyi İşle (ItemsReservedEvent ile Tetiklenir)
async function handleItemsReserved(event) {
    try {
        await paymentService.charge(event.orderId, amount);
        
        // Başarılı: Kargoya devam et
        eventBus.publish('PaymentCompletedEvent', { orderId: event.orderId });
    } catch (error) {
        // Tazmin: Siparişi iptal et (bu envanter serbest bırakmasını tetikleyecektir)
        eventBus.publish('OrderFailedEvent', { orderId: event.orderId });
    }
}

// Adım 3: Siparişi İptal Et (Tazmin Edici Eylem)
async function handleOrderFailed(event) {
    // Envanteri serbest bırak
    await inventoryService.release(event.orderId);
    // Zaten tahsil edilmişse ödemeyi iade et
    await paymentService.refund(event.orderId);
}

Temel Zorluklar ve Dikkat Edilmesi Gerekenler

Saga uygulamak, bazı tuzaklardan yoksun değildir. Geliştiriciler, ağ yeniden denemelerinin aynı adımın birden fazla kez yürütülmesine neden olabileceği için özdeşliği (idempotency) dikkatli bir şekilde ele almalıdır. Ayrıca, görünürlük (observability) kritik öneme sahiptir; dağıtık izleme olmadan, beş hizmette başarısız olan bir sagayı hata ayıklamak bir kabus olabilir. Son olarak, zaman aşımıları göz önünde bulundurun; bir hizmet yanıt vermez hale gelirse, saga bunu tespit edebilmeli ve sonsuza kadar beklemek yerine tazmini başlatabilmelidir.

Sonuç

Saga Deseni, mikroservis mimarilerinde dağıtık işlemleri yönetmek için sağlam bir çözümdür. Katı ACID işlemlerini esnek, tazmin edici iş akışlarıyla değiştirerek, sistemlerin gevşek bağlı kalmasını sağlarken veri tutarlılığını korur. Basitlik için koreografiyi mi yoksa kontrol için orkestrasyonu mu seçerseniz seçin, ölçeklenebilir ve dayanıklı dağıtık sistemler geliştiren her geliştirici için Saga Desenini anlamak zorunludur.

Share: