Mikroservisler Arasında Güvenilir İletişim: Transactional Outbox Pattern'a Derinlemesine Bir Bakış

[en] Read in English

2023-06-27

1. Giriş: Transactional Outbox Pattern’ın Tanımı ve Kullanım Alanları

Transactional Outbox Pattern, mikroservisler arasında güvenilir bir şekilde iletişim kurmayı sağlayan bir tasarım modelidir. Bu model, bir mikroservisin veritabanı işlemlerini ve dışarıya mesaj gönderme işlemlerini aynı işlem içinde gerçekleştirmesini sağlar. Bu sayede, her iki işlem de başarılı olur veya başarısız olur, böylece veri tutarlılığı sağlanır.

Bu modelin temel bileşenleri bir “Outbox” tablosu ve bir “Publisher” servisidir. İşlem gerçekleştiğinde, mikroservis önce veritabanında bir işlem gerçekleştirir ve ardından aynı işlem içinde Outbox tablosuna bir mesaj yazar. Publisher servisi daha sonra bu mesajı alır ve bir mesaj brokerına (örneğin, RabbitMQ, Kafka vb.) gönderir.

Transactional Outbox Pattern, özellikle aşağıdaki durumlarda kullanılır:

  • Veri tutarlılığı gerektiren durumlar: Bir mikroservis, bir işlemi gerçekleştirdikten sonra diğer mikroservislere bilgi vermek isteyebilir. Bu durumda, veritabanı işlemi ve mesaj gönderme işlemi aynı işlem içinde gerçekleşmelidir. Eğer herhangi biri başarısız olursa, her ikisi de geri alınmalıdır.

  • Yüksek erişilebilirlik gerektiren durumlar: Eğer bir mikroservis çökerse, Outbox tablosunda bekleyen mesajlar kaybolmaz. Publisher servisi mikroservis tekrar çalışmaya başladığında bu mesajları alabilir ve işleyebilir.

Aşağıdaki diyagram, Transactional Outbox Pattern’ın işleyişini göstermektedir:

Transactional Outbox Pattern Workflow

Bu diyagramda, bir istemci bir servise istek gönderir. Servis, bu isteği Outbox’a yazar ve istemciye işlemin başarıyla gerçekleştiğini bildirir. Daha sonra, Publisher servisi Outbox’dan mesajı alır ve bir Message Broker’a gönderir. Son olarak, Publisher mesajı Outbox’dan siler. Bu, Transactional Outbox Pattern’ın temel işleyişidir.

2. Transactional Outbox Pattern’ın Temel Bileşenleri: Outbox Tablosu ve Transactional Outbox Publisher

Transactional Outbox Pattern’ın iki ana bileşeni vardır: Outbox Tablosu ve Transactional Outbox Publisher. Bu bileşenler, bu modelin işleyişinde kritik bir rol oynar.

Outbox Tablosu: Bu tablo, bir mikroservis tarafından gönderilecek mesajları saklar. Bir mikroservis, bir işlemi gerçekleştirdiğinde, bu işlemle ilgili bilgileri içeren bir mesajı Outbox tablosuna yazar. Bu mesaj, daha sonra bir Message Broker’a gönderilmek üzere bekler.

Transactional Outbox Publisher: Bu servis, Outbox tablosundan mesajları alır ve bir Message Broker’a gönderir. Mesaj başarıyla gönderildikten sonra, Publisher servisi bu mesajı Outbox tablosundan siler.

3. Transactional Outbox Pattern’ın Çalışma Prensibi

Transactional Outbox Pattern’ın çalışma prensibi, bir dizi adımdan oluşur. Bu adımlar, bir mikroservisin bir işlemi gerçekleştirdiği ve bu işlemle ilgili bir mesajı bir Message Broker’a gönderdiği süreci kapsar.

Aşağıda, Transactional Outbox Pattern’ın çalışma prensibini adım adım gösteren bir diyagram bulunmaktadır:

Transactional Outbox Pattern Workflow Detailed

Bu diyagramda, aşağıdaki adımlar gösterilmektedir:

  1. İstemci, bir servise istek gönderir: Bu, bir işlemi başlatmak için yapılan bir istek olabilir.

  2. Servis, bir veritabanı işlemi gerçekleştirir: Bu, bir veri ekleme, güncelleme veya silme işlemi olabilir.

  3. Servis, Outbox’a bir mesaj yazar: Bu mesaj, gerçekleştirilen işlemle ilgili bilgileri içerir.

  4. Servis, istemciye işlemin başarıyla gerçekleştiğini bildirir: Bu, istemcinin işlemin durumunu bilmesini sağlar.

  5. Publisher, Outbox’dan mesajı alır: Publisher, Outbox’da bekleyen mesajları alır ve işler.

  6. Publisher, mesajı bir Message Broker’a gönderir: Bu, mesajın diğer mikroservislerle paylaşılmasını sağlar.

  7. Publisher, mesajı Outbox’dan siler: Bu, mesajın başarıyla işlendiğini ve artık gerekli olmadığını belirtir.

Bu adımlar, Transactional Outbox Pattern’ın temel çalışma prensibini oluşturur. Bu model, mikroservisler arasında güvenilir ve tutarlı bir iletişim sağlar.

4. Transactional Outbox Pattern’ın Avantajları

Transactional Outbox Pattern, mikroservisler arasında güvenilir ve tutarlı bir iletişim sağlar. Bu modelin birçok avantajı vardır:

Veri Tutarlılığı: Transactional Outbox Pattern, bir mikroservisin veritabanı işlemlerini ve dışarıya mesaj gönderme işlemlerini aynı işlem içinde gerçekleştirmesini sağlar. Bu sayede, her iki işlem de başarılı olur veya başarısız olur, böylece veri tutarlılığı sağlanır.

İşlem Güvenliği: Eğer bir mikroservis çökerse, Outbox tablosunda bekleyen mesajlar kaybolmaz. Publisher servisi mikroservis tekrar çalışmaya başladığında bu mesajları alabilir ve işleyebilir.

Yüksek Erişilebilirlik: Outbox tablosu ve Publisher servisi, bir mikroservisin çökmesi durumunda bile mesajların güvenli bir şekilde iletilmesini sağlar. Bu, mikroservisler arasında yüksek erişilebilirlik sağlar.

5. Transactional Outbox Pattern’ın Dezavantajları

Her ne kadar Transactional Outbox Pattern, mikroservisler arasında güvenilir ve tutarlı bir iletişim sağlasa da, bu modelin bazı dezavantajları da bulunmaktadır:

Ekstra Depolama ve İşlem Maliyeti: Outbox tablosu, bir mikroservis tarafından gönderilecek mesajları saklar. Bu, ekstra depolama alanı gerektirir. Ayrıca, Publisher servisinin Outbox’dan mesajları alıp bir Message Broker’a göndermesi, ekstra işlem maliyeti oluşturur.

Zamanlama ve Sıralama Sorunları: Publisher servisi, Outbox’dan mesajları alır ve bir Message Broker’a gönderir. Ancak, bu işlem asenkron olduğu için, mesajların sırası karışabilir. Bu, zamanlama ve sıralama sorunlarına neden olabilir.

Kompleksite: Transactional Outbox Pattern, bir mikroservisin işleyişini daha karmaşık hale getirir. Bir mikroservis, hem veritabanı işlemlerini hem de dışarıya mesaj gönderme işlemlerini yönetmek zorundadır. Bu, hata olasılığını artırabilir ve hata ayıklamayı zorlaştırabilir.

Bu dezavantajlar, Transactional Outbox Pattern’ın kullanımını sınırlayabilir. Ancak, bu modelin sunduğu avantajlar, genellikle bu dezavantajları aşar. Bu nedenle, Transactional Outbox Pattern, mikroservisler arasında güvenilir ve tutarlı bir iletişim sağlamak için sıkça kullanılan bir modeldir.

6. Transactional Outbox Pattern’ın Uygulama Örnekleri: Gerçek Dünya C# ve Go Örnekleri

Transactional Outbox Pattern’ın gerçek dünya uygulamalarını daha iyi anlamak için C# ve Go dillerinde örnekler üzerinden gidelim.

C# Örneği

C#‘ta Transactional Outbox Pattern’ı uygulamak için Entity Framework Core gibi bir ORM (Object-Relational Mapping) aracı kullanabiliriz. Bu örnekte, bir e-ticaret uygulamasında bir siparişin oluşturulduğunu ve bu siparişin detaylarının bir Outbox tablosuna yazıldığını düşünelim:

public class OrderService
{
    private readonly DbContext _context;

    public OrderService(DbContext context)
    {
        _context = context;
    }

    public async Task CreateOrderAsync(Order order)
    {
        using var transaction = _context.Database.BeginTransaction();

        try
        {
            // Save the order to the database
            _context.Orders.Add(order);
            await _context.SaveChangesAsync();

            // Write a message to the outbox
            var outboxMessage = new OutboxMessage(order.Id, "OrderCreated", JsonConvert.SerializeObject(order));
            _context.OutboxMessages.Add(outboxMessage);

            await _context.SaveChangesAsync();

            await transaction.CommitAsync();
        }
        catch
        {
            await transaction.RollbackAsync();
            throw;
        }
    }
}

Bu örnekte, CreateOrderAsync metodu bir veritabanı işlemi başlatır. Bu işlem içinde, sipariş veritabanına kaydedilir ve ardından Outbox tablosuna bir mesaj eklenir. Eğer herhangi bir hata oluşursa, işlem geri alınır.

Go Örneği

Go’da Transactional Outbox Pattern’ı uygulamak için SQL işlemlerini kullanabiliriz. Bu örnekte, bir kullanıcının kaydının oluşturulduğunu ve bu kullanıcının detaylarının bir Outbox tablosuna yazıldığını düşünelim:

package main

import (
	"database/sql"
	"encoding/json"
	"log"
)

type User struct {
	Id   int
	Name string
	Email string
}

type OutboxMessage struct {
	EntityId   int
	EntityType string
	EventType  string
	Payload    string
}

func CreateUser(db *sql.DB, user User) error {
	tx, err := db.Begin()
	if err != nil {
		return err
	}

	// Save the user to the database
	_, err = tx.Exec("INSERT INTO Users (Name, Email) VALUES (?, ?)", user.Name, user.Email)
	if err != nil {
		tx.Rollback()
		return err
	}

	// Write a message to the outbox
	payload, err := json.Marshal(user)
	if err != nil {
		tx.Rollback()
		return err
	}
	outboxMessage := OutboxMessage{EntityId: user.Id, EntityType: "User", EventType: "UserCreated", Payload: string(payload)}
	_, err = tx.Exec("INSERT INTO Outbox (EntityId, EntityType, EventType, Payload) VALUES (?, ?, ?, ?)", outboxMessage.EntityId, outboxMessage.EntityType, outboxMessage.EventType, outboxMessage.Payload)
	if err != nil {
		tx.Rollback()
		return err
	}

	return tx.Commit()
}

7. Transactional Outbox Pattern’ın Alternatifleri

Transactional Outbox Pattern, mikroservisler arasında güvenilir ve tutarlı bir iletişim sağlamak için kullanılan bir modeldir. Ancak, bu modelin alternatifleri de bulunmaktadır. İki popüler alternatif, Two-Phase Commit (2PC) ve Saga Pattern’dir.

Two-Phase Commit (2PC): Bu model, bir işlemi birden çok kaynak arasında atomik bir şekilde gerçekleştirmek için kullanılır. İlk aşamada, işlem koordinatörü tüm kaynaklara işlemi gerçekleştirme niyetini bildirir. Eğer tüm kaynaklar olumlu yanıt verirse, ikinci aşamada işlem koordinatörü tüm kaynaklara işlemi gerçekleştirmelerini söyler. Ancak, bu modelin bir dezavantajı vardır: Eğer bir kaynak çökerse veya ağda bir hata oluşursa, tüm işlem durur ve kaynaklar kilitlenir.

Saga Pattern: Bu model, bir işlemi birden çok adıma böler ve her adımı ayrı bir işlem olarak gerçekleştirir. Eğer bir adımda bir hata oluşursa, Saga Pattern önceki adımların tersini gerçekleştirir (compensating transactions). Bu model, uzun süreli işlemler ve mikroservisler arasında işlemler için uygundur. Ancak, bu modelin bir dezavantajı vardır: İşlemlerin sırası ve zamanlaması karmaşık olabilir ve hata durumunda geri alınması gereken işlemlerin yönetilmesi zor olabilir.

Bu alternatifler, Transactional Outbox Pattern’ın sunduğu avantajları sunar, ancak kendi dezavantajlarına sahiptirler. Hangi modelin kullanılacağı, uygulamanın gereksinimlerine ve kısıtlamalarına bağlıdır.

Sonuç: Transactional Outbox Pattern’ın Genel Değerlendirmesi

Transactional Outbox Pattern, mikroservisler arasında güvenilir ve tutarlı bir iletişim sağlamak için etkili bir modeldir. Bu model, bir mikroservisin veritabanı işlemlerini ve dışarıya mesaj gönderme işlemlerini aynı işlem içinde gerçekleştirmesini sağlar. Bu sayede, her iki işlem de başarılı olur veya başarısız olur, böylece veri tutarlılığı sağlanır.

Bu modelin birçok avantajı vardır. Öncelikle, veri tutarlılığı sağlar. İkincil olarak, işlem güvenliği sunar. Eğer bir mikroservis çökerse, Outbox tablosunda bekleyen mesajlar kaybolmaz. Üçüncü olarak, yüksek erişilebilirlik sağlar. Outbox tablosu ve Publisher servisi, bir mikroservisin çökmesi durumunda bile mesajların güvenli bir şekilde iletilmesini sağlar.

Ancak, bu modelin bazı dezavantajları da vardır. Ekstra depolama ve işlem maliyeti gerektirir. Zamanlama ve sıralama sorunlarına neden olabilir. Ayrıca, bir mikroservisin işleyişini daha karmaşık hale getirir.

Bu modelin alternatifleri arasında Two-Phase Commit (2PC) ve Saga Pattern bulunur. Ancak, hangi modelin kullanılacağı, uygulamanın gereksinimlerine ve kısıtlamalarına bağlıdır.

Sonuç olarak, Transactional Outbox Pattern, mikroservisler arasında güvenilir ve tutarlı bir iletişim sağlamak için önemli bir modeldir. Bu modelin gelecekte daha fazla otomasyon, entegrasyon, performans ve ölçeklenebilirlik sunması beklenmektedir. Bu nedenle, Transactional Outbox Pattern’ın kullanımı, modern yazılım geliştirme uygulamalarında önemli bir yer tutmaya devam edecektir.



Bu gibi daha fazla gönderi...

Her Servisin Gizli Hazinesi: Mikroservislerle Database Per Service Hikayesi

2023-05-26 | #database-per-service #microservice

Bilgisayarlar Diyarı’nın bir başka köşesinde, Mikroservisler Şehri’nde, her mikroservisin kendi veritabanına sahip olduğu farklı bir dünya vardı. Bu model, “Her Servis için Veritabanı” olarak adlandırılmıştı. Bu dünyada, her mikroservis kendi hazine sandığına, yani kendi veritabanına sahipti. Bu sandıklar, her bir mikroservisin ihtiyaç duyduğu verileri içerirdi ve sadece ilgili mikroservis tarafından erişilebilirdi. Tıpkı bir masal kahramanının kendi hazine sandığına sahip olması gibi, her mikroservis de kendi veritabanına sahipti. Bir gün, Sipariş Mikroservisi, yeni bir sipariş oluşturma görevi aldı.

Devamı 


Orkestra Şefinin Hikayesi: Mikroservislerle Orkestrasyon Temelli Saga

2023-05-26 | #microservice #orchestration-based-saga #saga-pattern

Bilgisayarlar Diyarı’nın bir başka köşesinde, Mikroservisler Şehri’nde, tüm mikroservislerin belirli bir senfoniye göre hareket ettiği başka bir dünya vardı. Bu dünyada, tüm mikroservisler tek bir orkestra şefi tarafından yönetilirdi ve bu yönetim modeline “Orkestrasyon Temelli Saga” adı verilmişti. Bu, büyük bir orkestradaki müzik performansına benzer. Tıpkı bir orkestra şefinin tüm müzisyenlere ne zaman hangi notaları çalacaklarını söylediği gibi, burada da Orkestra Şefi Mikroservisi, diğer tüm mikroservislerin ne zaman ve nasıl hareket edeceğini belirler.

Devamı 


Mikroservisler Ülkesi'nde Büyülü Dans: Koreografi Temelli Saga

2023-05-26 | #choreography-based-saga #microservice #saga-pattern

Bir zamanlar, Bilgisayarlar Diyarı’nda Mikroservisler Ülkesi diye bir yer vardı. Bu ülkede minik minik hizmetçiler, yani mikroservisler, kendi görevlerini layıkıyla yerine getiriyorlardı. Onların her biri, kendi evlerinde -yani kendi sunucularında- yaşıyor ve kendi işlerini görüyorlardı. Bu işler o kadar küçük ve özelleşmişti ki, her bir mikroservis kendi görevini harika bir şekilde yerine getirebiliyordu. Ama bir sorun vardı: bazen bir işi tamamlamak için birkaç mikroservisin birlikte çalışması gerekiyordu. İşte bu noktada, dansın ve hareketin büyüleyici dünyası devreye giriyordu: “Koreografi Temelli Saga” olarak bilinen bir model.

Devamı 