Gereksinimler ve Ön Hazırlık
Bu uygulamayı gerçekleştirmek için bilgisayarınızda Node.js'in güncel bir sürümü (2026 itibarıyla LTS sürümü olan v22 veya üzeri önerilir) kurulu olmalıdır. Ayrıca, mesajları yönetecek olan RabbitMQ sunucusuna ihtiyacınız var. RabbitMQ'yu yerel makinenizde Docker kullanarak saniyeler içinde ayağa kaldırabilirsiniz.
Projenizi başlatmak için bir klasör oluşturun ve gerekli kütüphaneleri yükleyin:
mkdir mikroservis-kuyruk
cd mikroservis-kuyruk
npm init -y
npm install amqplib dotenv
Burada amqplib, RabbitMQ ile Node.js arasında köprü kuran standart kütüphanedir. dotenv ise konfigürasyon ayarlarını güvenli bir şekilde yönetmemize yardımcı olur.
RabbitMQ Sunucusunu Docker ile Kurma
Mikroservisleriniz için mesaj kuyruğu yapısını test ederken, RabbitMQ'nun yönetim paneline erişebilmek büyük kolaylık sağlar. Aşağıdaki komutla RabbitMQ'yu yönetim arayüzü ile birlikte çalıştırabilirsiniz.
docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management
Bu komut, 5672 numaralı portu mesajlaşma için, 15672 numaralı portu ise tarayıcınızdan yönetim paneline (guest/guest bilgileriyle) erişmeniz için açar. Docker'ın sisteminizde yüklü olduğundan emin olun.
Mesaj Üretici (Producer) Servisini Oluşturma
Mesaj üretici, sisteme bir veri girişi olduğunda (örneğin yeni bir kullanıcı kaydı) bu veriyi kuyruğa gönderen servistir. Üretici, mesajın nereye gittiğiyle ilgilenmez; sadece mesajı "exchange"e (değiş tokuş noktası) bırakır.
const amqp = require('amqplib');
async function mesajGonder(mesaj) {
const baglanti = await amqp.connect('amqp://localhost');
const kanal = await baglanti.createChannel();
const kuyrukIsmi = 'kullanici_kayitlari';
await kanal.assertQueue(kuyrukIsmi, { durable: true });
kanal.sendToQueue(kuyrukIsmi, Buffer.from(JSON.stringify(mesaj)), { persistent: true });
console.log("Mesaj gönderildi:", mesaj);
setTimeout(() => { baglanti.close(); }, 500);
}
mesajGonder({ id: 1, email: 'test@ornek.com' });
Burada durable: true parametresi, RabbitMQ yeniden başlasa bile kuyruğun silinmemesini sağlar. persistent: true ise mesajın diskte saklanmasını garanti eder; bu, veri kaybını önlemek için kritik bir güvenlik önlemidir.
Mesaj Kuyruğu Yöntemlerinin Karşılaştırılması
Mikroservisler arası iletişimde farklı stratejiler mevcuttur. İhtiyacınıza göre doğru yöntemi seçmek mimari başarınızı belirler.
| Yöntem | Avantaj | Dezavantaj |
|---|---|---|
| Direct Exchange | Hızlı ve basit, birebir eşleşme. | Esneklik düşük. |
| Fanout Exchange | Mesajı tüm kuyruklara dağıtır. | Filtreleme yapılamaz. |
| Topic Exchange | Desen tabanlı (pattern) yönlendirme. | Karmaşıklığı yönetmek zor olabilir. |
Hata Yönetimi ve Dead Letter Queues (DLQ)
Üretim ortamında mesajlar bazen işlenemez (örneğin geçersiz veri formatı). Bu durumda mesajın kaybolmaması için "Dead Letter Queue" (Ölü Mesaj Kuyruğu) yapısı kurulmalıdır.
// Kanal oluştururken hata kuyruğu tanımlama
await kanal.assertQueue('ana_kuyruk', {
deadLetterExchange: 'dlx_exchange',
deadLetterRoutingKey: 'dlx_key'
});
Bu yapı, işlenemeyen mesajları otomatik olarak ayrı bir kuyruğa taşır. Böylece ana sisteminiz kilitlenmeden, hatalı mesajları daha sonra analiz edebilirsiniz.
Güvenlik Uyarısı: Üretim ortamında RabbitMQ bağlantı dizelerinizi asla kod içine gömmeyin.
process.env.RABBITMQ_URLgibi ortam değişkenlerini kullanın. Ayrıca, RabbitMQ üzerinde mutlaka güçlü parolalar tanımlayın ve ağ erişimini sadece ilgili servislerin IP adreslerine kısıtlayın.
Sıkça Sorulan Sorular
Node.js üzerinde mesaj kuyruğu kullanmak performansı düşürür mü?
Tam tersine, mesaj kuyruğu kullanmak ana iş parçacığınızı (event loop) rahatlatır. Uzun süren işlemleri kuyruğa atarak, API yanıt sürelerinizi ciddi oranda düşürebilirsiniz.
Mesajların sırasını garanti edebilir miyim?
Tek bir tüketici (consumer) kullandığınız sürece mesajlar gönderilme sırasıyla işlenir. Ancak çoklu tüketici kullanıyorsanız, mesaj sırasını garanti etmek için "Consistent Hashing" yöntemlerini araştırmalısınız.
RabbitMQ yerine Redis kullanılabilir mi?
Redis, Pub/Sub yapısı için hızlıdır ancak RabbitMQ kadar gelişmiş mesaj onaylama (acknowledgement) ve dayanıklılık (durability) özelliklerine sahip değildir. Karmaşık mikroservisler için RabbitMQ daha güvenli bir tercihtir.
Mesaj kuyruğunda veri güvenliği nasıl sağlanır?
Mesaj içeriğini şifreleyerek gönderebilirsiniz (AES-256 gibi). Ayrıca, TLS/SSL kullanarak RabbitMQ ile servisler arasındaki iletişimi şifrelemeniz önerilir.
Kuyruk dolarsa ne olur?
RabbitMQ, kuyruk boyutu sınırına ulaştığında yeni mesajları reddedebilir veya en eski mesajları silebilir. Bu durumu izlemek için RabbitMQ'nun sunduğu metrikleri (Prometheus ile) takip etmelisiniz.
Sorumluluk Reddi: Bu makalede paylaşılan kod örnekleri eğitim amaçlıdır. Üretim ortamında kullanmadan önce güvenlik denetimlerinden geçirmeli ve sisteminize uygun hata yönetimi mekanizmalarını (retry logic, circuit breaker) entegre etmelisiniz.
Mikroservislerde Mesaj Kuyruğu İçin İleri Seviye İzleme ve Hata Ayıklama
Mesaj kuyruğu sistemlerinde en büyük zorluk, "kaybolan" mesajların izini sürmektir. Dağıtık sistemlerde bir mesajın üreticiden çıkıp tüketiciye ulaşana kadar hangi aşamalardan geçtiğini anlamak için Correlation ID (İlişkilendirme Kimliği) kullanımı hayati önem taşır. Her mesajın başlığına benzersiz bir ID ekleyerek, loglarınızda bu ID üzerinden arama yapabilir ve işlem akışını görselleştirebilirsiniz.
Aşağıdaki örnekte, bir mesajı gönderirken nasıl benzersiz bir takip kimliği ekleyeceğinizi görebilirsiniz:
const { v4: uuidv4 } = require('uuid');
async function publishMessage(channel, queue, data) {
const correlationId = uuidv4();
const message = {
payload: data,
metadata: {
correlationId,
timestamp: new Date().toISOString()
}
};
channel.sendToQueue(queue, Buffer.from(JSON.stringify(message)), {
correlationId: correlationId,
persistent: true
});
console.log(`Mesaj gönderildi. ID: ${correlationId}`);
}
Mesaj Kuyruğu Sistemlerinde Test Stratejileri
Mikroservisler arası iletişimde birim testleri (unit tests) tek başına yeterli değildir. Mesaj kuyruğu kullanan servisler için Entegrasyon Testleri yazarken, gerçek bir RabbitMQ örneğini ayağa kaldırmak yerine amqplib-mocks gibi kütüphaneler veya Docker üzerinden geçici bir konteyner kullanmak en sağlıklı yöntemdir.
Test süreçlerinizde şu senaryoları mutlaka simüle etmelisiniz:
- Kuyruk Doluluğu: Kuyruğa çok hızlı veri basıldığında tüketicinin (consumer) yavaş kalması durumunda sistemin nasıl tepki verdiği.
- Bağlantı Kopması: RabbitMQ sunucusu ile bağlantı kesildiğinde, üreticinin mesajları hafızada tutup tutmadığı veya hata fırlatıp fırlatmadığı.
- Mesaj İşleme Hatası: Tüketici servisin mesajı işlerken hata alması durumunda, mesajın tekrar kuyruğa dönüp dönmediği (nack/requeue mekanizması).
Örnek bir hata simülasyonu ve yeniden deneme (retry) mantığı:
channel.consume(queue, (msg) => {
try {
const content = JSON.parse(msg.content.toString());
// İşleme mantığı
channel.ack(msg);
} catch (error) {
console.error("İşleme hatası, mesaj tekrar kuyruğa alınıyor...");
// Mesajı reddet ve kuyruğa geri gönder
channel.nack(msg, false, true);
}
}, { noAck: false });
Performans Optimizasyonu İçin İpuçları
Node.js'in olay döngüsünü (event loop) kilitlememek için mesajları işlerken ağır CPU operasyonlarını worker_threads modülüne devretmelisiniz. Ayrıca, mesaj kuyruğunda performans artışı için şu teknikleri uygulayın:
| Teknik | Avantajı |
|---|---|
| Prefetch Count | Tüketicinin aynı anda kaç mesajı işleyeceğini sınırlar, kaynak tüketimini dengeler. |
| Batching | Mesajları tek tek değil, paketler halinde göndererek ağ trafiğini azaltır. |
| Connection Pooling | Her mesaj için yeni bağlantı açmak yerine mevcut bağlantıları yeniden kullanır. |
channel.prefetch(10) ayarını kullanarak, bir tüketicinin aynı anda en fazla 10 mesajı işlemesini sağlayabilir, böylece sistemin aşırı yüklenmesini engelleyebilirsiniz.
Sonuç
Node.js ile mikroservis mimarisi için bir mesaj kuyruğu kurmak, sisteminizin esnekliğini ve hata toleransını artıran en önemli adımlardan biridir. Bu rehberde, RabbitMQ'nun temel çalışma mantığını, üretici ve tüketici servislerinin nasıl kodlanacağını ve hata yönetimi için gerekli stratejileri inceledik. Bir sonraki adım olarak, sisteminize Circuit Breaker (devre kesici) desenini ekleyerek, servislerinizden biri çöktüğünde mesaj trafiğini nasıl yöneteceğinizi çalışmanızı öneririm.


Yorumlar (0)
Yorum Yaz