Gereksinimler ve Ön Hazırlık
RabbitMQ ile çalışmaya başlamadan önce geliştirme ortamınızın hazır olması gerekir. İhtiyacınız olan temel araçlar şunlardır:
- .NET 8 veya 9 SDK (2026 standartları gereği en güncel sürüm önerilir).
- RabbitMQ Server (Yerel makinenizde Docker üzerinde çalıştırmanız en pratik yöntemdir).
- RabbitMQ.Client kütüphanesi (NuGet üzerinden projenize eklenmelidir).
- Visual Studio 2022 veya JetBrains Rider IDE.
Docker üzerinden RabbitMQ kurulumu yapmak için terminalinize şu komutu yazabilirsiniz:
docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management
Bu komut, RabbitMQ sunucusunu 5672 portunda (mesajlaşma için) ve 15672 portunda (yönetim paneli için) başlatacaktır. Yönetim paneline tarayıcınızdan http://localhost:15672 adresinden erişebilirsiniz (Varsayılan kullanıcı adı: guest, şifre: guest).
RabbitMQ Bağlantı Yönetimi
C# projelerinde RabbitMQ ile etkileşime geçmek için ilk adım, sunucuya güvenli bir bağlantı oluşturmaktır. Bağlantı nesneleri (Connection) ağır nesnelerdir; bu nedenle uygulamanızın yaşam döngüsü boyunca tek bir bağlantı (Singleton) kullanmanız önerilir.
using RabbitMQ.Client;
var factory = new ConnectionFactory() { HostName = "localhost" };
using var connection = factory.CreateConnection();
using var channel = connection.CreateModel();
channel.QueueDeclare(queue: "siparis_kuyrugu",
durable: true,
exclusive: false,
autoDelete: false,
arguments: null);
Yukarıdaki kod bloğunda ConnectionFactory ile sunucuya bağlanıyoruz ve QueueDeclare metodu ile "siparis_kuyrugu" adında, sunucu yeniden başlatılsa bile silinmeyecek (durable) bir kuyruk tanımlıyoruz.
Mesaj Gönderen (Producer) Uygulama Geliştirme
Producer, mesajı kuyruğa bırakan taraftır. Mesajlar genellikle JSON formatında serialize edilerek gönderilir. Gönderim sırasında mesajın kalıcılığını sağlamak için IBasicProperties kullanılır.
var message = "Yeni bir sipariş geldi: #12345";
var body = System.Text.Encoding.UTF8.GetBytes(message);
var properties = channel.CreateBasicProperties();
properties.Persistent = true;
channel.BasicPublish(exchange: "",
routingKey: "siparis_kuyrugu",
basicProperties: properties,
body: body);
Bu kodda, mesajı byte dizisine çevirip BasicPublish metodu ile kuyruğa gönderiyoruz. properties.Persistent = true ayarı, mesajın diske yazılmasını sağlayarak sunucu çökmesi durumunda veri kaybını önler.
Mesaj İşleyen (Consumer) Uygulama Geliştirme
Consumer, kuyruğu dinleyen ve mesaj geldiğinde tetiklenen taraftır. EventingBasicConsumer yapısını kullanarak mesajları asenkron bir şekilde işleyebiliriz.
var consumer = new EventingBasicConsumer(channel);
consumer.Received += (model, ea) =>
{
var body = ea.Body.ToArray();
var message = System.Text.Encoding.UTF8.GetString(body);
Console.WriteLine($"İşlenen Mesaj: {message}");
channel.BasicAck(deliveryTag: ea.DeliveryTag, multiple: false);
};
channel.BasicConsume(queue: "siparis_kuyrugu",
autoAck: false,
consumer: consumer);
Burada en kritik nokta autoAck: false kullanımıdır. Mesajın işlendiğini onaylamak için BasicAck metodunu manuel çağırıyoruz. Eğer işlem sırasında hata alırsanız, BasicNack ile mesajı kuyruğa geri döndürebilirsiniz.
Mesajlaşma Mimarisi Karşılaştırması
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| Doğrudan Kuyruk | Basit ve hızlı | Esnek değil |
| Exchange (Fanout) | Broadcast yayını | Tüm kuyruklara gider |
| Exchange (Topic) | Filtreli yönlendirme | Karmaşık yapı |
Güvenlik Uyarısı: RabbitMQ bağlantı bilgilerini asla kod içerisinde hard-coded (sabit) bırakmayın. Üretim ortamında
appsettings.jsonveya Azure Key Vault gibi güvenli konfigürasyon yönetim araçlarını kullanın. Ayrıca, mesaj içeriğinde hassas kişisel veriler (KVKK kapsamındaki veriler) varsa, mesajları mutlaka şifreleyerek (Encryption) gönderin.
Mesaj Kuyruğu Tasarımında Dikkat Edilmesi Gerekenler
Mesaj kuyruğu mimarisi kurarken şu noktalara dikkat etmelisiniz:
- Idempotency (Eşdeğerlik): Aynı mesajın iki kez işlenmesi durumunda sistemin bozulmadığından emin olun.
- Dead Letter Queue (DLQ): İşlenemeyen mesajları ayrı bir "ölü mesaj" kuyruğuna yönlendirerek analiz edin.
- Hata Yönetimi: Try-catch bloklarını kullanarak hata durumunda mesajın kuyruktan silinmemesini sağlayın.
Sıkça Sorulan Sorular
RabbitMQ ile Kafka arasındaki temel fark nedir?
RabbitMQ, mesaj teslimatına ve esnek yönlendirme kurallarına odaklanan bir "mesaj broker"ıdır. Kafka ise yüksek hacimli veri akışlarını depolayan ve işleyen bir "olay akış platformu"dur.
Mesajlar kuyrukta ne kadar süre kalabilir?
Varsayılan olarak mesajlar siz silene kadar kalır, ancak "Time-to-Live" (TTL) özelliği ile mesajların belirli bir süre sonra otomatik silinmesini sağlayabilirsiniz.
Aynı anda birden fazla Consumer çalıştırabilir miyim?
Evet, RabbitMQ mesajları "Round-robin" algoritması ile bağlı olan Consumer'lara dağıtır. Bu, sisteminizin yatayda ölçeklenmesini sağlar.
Mesajların sırasını garanti edebilir miyim?
Tek bir kuyrukta mesajlar FIFO (İlk giren ilk çıkar) prensibiyle çalışır. Ancak birden fazla Consumer olduğunda, işleme hızlarına bağlı olarak sıralama değişebilir.
RabbitMQ'nun performansı nasıl izlenir?
Yönetim paneli (Management Plugin) üzerinden kuyruk derinliğini, mesaj giriş/çıkış hızlarını ve bağlantı durumlarını anlık olarak izleyebilirsiniz.
Sorumluluk Reddi: Bu makaledeki kod örnekleri eğitim amaçlıdır. Üretim ortamında kullanılacak sistemlerde mesajların güvenliği, kuyrukların yedekliliği ve hata toleransı (fault tolerance) için kapsamlı testler yapılması ve profesyonel mimari standartlarına uyulması kullanıcının sorumluluğundadır.
RabbitMQ'da Hata Yönetimi ve Dead Letter Exchange (DLX) Stratejileri
Gerçek dünya uygulamalarında mesajların işlenmesi sırasında beklenmedik hatalar oluşabilir. Bir mesajın işlenememesi durumunda, mesajı kaybetmek yerine onu "Dead Letter Exchange" (DLX) adı verilen özel bir kuyruğa yönlendirmek, sistemin güvenilirliğini artırır. Bu yaklaşım, hatalı mesajların neden işlenemediğini analiz etmenize ve daha sonra tekrar denemenize olanak tanır.
Dead Letter Exchange Kurulumu
Bir kuyruğu DLX ile ilişkilendirmek için, kuyruk tanımlama aşamasında x-dead-letter-exchange argümanını belirtmeniz gerekir. Aşağıdaki C# örneği, başarısız olan mesajların nasıl yönlendirileceğini göstermektedir:
var arguments = new Dictionary
{
{ "x-dead-letter-exchange", "dlx_exchange" },
{ "x-dead-letter-routing-key", "failed_messages" }
};
channel.QueueDeclare(queue: "main_queue",
durable: true,
exclusive: false,
autoDelete: false,
arguments: arguments);
channel.ExchangeDeclare("dlx_exchange", ExchangeType.Direct);
channel.QueueDeclare("failed_messages", true, false, false, null);
channel.QueueBind("failed_messages", "dlx_exchange", "failed_messages");
Bu yapılandırmadan sonra, BasicNack veya BasicReject metotlarını requeue: false parametresi ile çağırdığınızda, mesaj otomatik olarak failed_messages kuyruğuna taşınacaktır.
RabbitMQ Performansını Optimize Etme İpuçları
Yüksek trafikli sistemlerde RabbitMQ'nun verimli çalışması için bazı konfigürasyonel iyileştirmeler yapılması kritik öneme sahiptir. Özellikle mesajların işlenme hızı ve ağ üzerindeki yük, sistemin genel başarısını doğrudan etkiler.
Prefetch Count Ayarı
Varsayılan olarak RabbitMQ, kuyruktaki tüm mesajları Consumer'a göndermeye çalışır. Ancak, Consumer'ın işleme kapasitesi sınırlıysa bu durum bellek sorunlarına yol açabilir. BasicQos metodu ile aynı anda kaç mesajın işlenmek üzere "prefetch" edileceğini belirleyebilirsiniz.
// Aynı anda sadece 10 mesajın işlenmek üzere alınmasını sağlar
channel.BasicQos(prefetchSize: 0, prefetchCount: 10, global: false);
Mesaj Kalıcılığı (Persistence)
Eğer mesajlarınızın RabbitMQ sunucusu yeniden başlatıldığında kaybolmamasını istiyorsanız, hem kuyruğu durable: true olarak tanımlamalı hem de mesaj gönderirken IBasicProperties üzerinden Persistent özelliğini aktif etmelisiniz:
var properties = channel.CreateBasicProperties();
properties.Persistent = true;
channel.BasicPublish(exchange: "",
routingKey: "task_queue",
basicProperties: properties,
body: messageBody);
Bu ayarlar, mesajın disk üzerinde saklanmasını sağlayarak veri kaybı riskini minimize eder, ancak disk I/O operasyonları nedeniyle performansta küçük bir düşüşe neden olabilir. Bu nedenle, sadece kritik veriler için kalıcılık özelliğini kullanmanız önerilir.
Sonuç
C# ile RabbitMQ kullanarak mesaj kuyruğu mimarisi kurmak, uygulamalarınızın dayanıklılığını ve performansını artıran en temel adımlardan biridir. Bu rehberde, bağlantı yönetiminden mesaj tüketimine kadar olan süreci adım adım inceledik. Bir sonraki adım olarak, RabbitMQ'da "Exchange" türlerini (Direct, Topic, Fanout) detaylıca inceleyerek daha karmaşık yönlendirme senaryoları üzerinde pratik yapmanızı öneririm.


Yorumlar (0)
Yorum Yaz