RabbitMQ Quorum Queue Yapılandırması ve Klasik Kuyruktan Geçiş Rehberi
Production ortamında mesaj kaybı yaşamak, gecenin 3’ünde pager’ın çalması demektir. RabbitMQ’nun klasik kuyruklarını kullanan sistemlerde node çöktüğünde mesajların buharlaşması, pek çok ekibin acı tecrübeyle öğrendiği bir gerçek. İşte bu yüzden RabbitMQ 3.8 ile hayatımıza giren Quorum Queue yapısı, ciddi bir üretim ortamı için artık tercih değil zorunluluk haline geldi. Bu yazıda klasik kuyruktan quorum queue’ya nasıl geçeceğini, nelere dikkat etmen gerektiğini ve production’da karşılaşabileceğin senaryoları ele alacağız.
Quorum Queue Nedir, Neden Önemli?
Klasik RabbitMQ kuyruklarında replikasyon, mirrored queue mekanizmasıyla sağlanıyordu. Bu yapıda master node düşünce slave node master oluyordu, ama bu geçiş süreci sağlıklı değildi. Split-brain durumlarında mesaj kaybı veya duplicate mesaj üretimi ciddi sorunlara yol açıyordu.
Quorum Queue, Raft consensus algoritması üzerine inşa edilmiş bir yapı. Basit anlatımla, bir mesajın kalıcı sayılabilmesi için cluster’daki node’ların çoğunluğunun (quorum) onaylaması gerekiyor. Örneğin 3 node’lu bir cluster’da en az 2 node onaylamalı. 5 node’lu bir cluster’da en az 3.
Bu yapının sana kazandırdıkları:
- Mesaj garantisi: Node çöküşlerinde mesaj kaybı yaşamazsın
- Lider seçimi: Raft sayesinde otomatik ve tutarlı leader election
- Poison message yönetimi: Sürekli hata veren mesajlar için delivery-limit özelliği
- Daha az konfigürasyon: Mirrored queue’nun karmaşık policy yapısına gerek yok
- At-least-once delivery: Mesajlar en az bir kez işlenir garantisi
Dezavantajları da görmezden gelemeyiz tabii:
- Disk kullanımı klasik kuyruğa göre daha fazla
- Lazy mode varsayılan olarak aktif, bu yüzden memory kullanımı farklı davranır
- Geçici (transient) mesajları desteklemez, tüm mesajlar persistent sayılır
- TTL bazlı özellikler kısıtlı
Cluster Hazırlığı
Quorum queue için en az 3 node’lu bir RabbitMQ cluster’ına ihtiyacın var. Tek node veya 2 node’lu yapılarda quorum elde edemezsin.
Önce mevcut cluster durumunu kontrol et:
# Cluster durumunu görüntüle
rabbitmqctl cluster_status
# Node'ların sağlık durumunu kontrol et
rabbitmq-diagnostics check_running
rabbitmq-diagnostics check_local_alarms
# Disk ve memory alarm durumunu gör
rabbitmqctl status | grep -A5 "alarms"
Eğer cluster’ın yoksa ve test ortamı kuruyorsan, Docker Compose ile hızlıca 3 node’lu bir yapı ayağa kaldırabilirsin:
# docker-compose.yml
version: '3.8'
services:
rabbitmq1:
image: rabbitmq:3.12-management
hostname: rabbitmq1
environment:
RABBITMQ_ERLANG_COOKIE: "SECRETCOOKIE123"
RABBITMQ_DEFAULT_USER: admin
RABBITMQ_DEFAULT_PASS: adminpass
ports:
- "15672:15672"
- "5672:5672"
rabbitmq2:
image: rabbitmq:3.12-management
hostname: rabbitmq2
environment:
RABBITMQ_ERLANG_COOKIE: "SECRETCOOKIE123"
RABBITMQ_DEFAULT_USER: admin
RABBITMQ_DEFAULT_PASS: adminpass
ports:
- "15673:15672"
- "5673:5672"
rabbitmq3:
image: rabbitmq:3.12-management
hostname: rabbitmq3
environment:
RABBITMQ_ERLANG_COOKIE: "SECRETCOOKIE123"
RABBITMQ_DEFAULT_USER: admin
RABBITMQ_DEFAULT_PASS: adminpass
ports:
- "15674:15672"
- "5674:5672"
# Container'ları ayağa kaldır
docker-compose up -d
# rabbitmq2 ve rabbitmq3'ü cluster'a ekle
docker exec rabbitmq2 rabbitmqctl stop_app
docker exec rabbitmq2 rabbitmqctl join_cluster rabbit@rabbitmq1
docker exec rabbitmq2 rabbitmqctl start_app
docker exec rabbitmq3 rabbitmqctl stop_app
docker exec rabbitmq3 rabbitmqctl join_cluster rabbit@rabbitmq1
docker exec rabbitmq3 rabbitmqctl start_app
# Cluster durumunu doğrula
docker exec rabbitmq1 rabbitmqctl cluster_status
Quorum Queue Oluşturma
Cluster hazır olduğunda quorum queue oluşturmak oldukça basit:
# Management API ile quorum queue oluştur
curl -u admin:adminpass -X PUT http://localhost:15672/api/queues/%2F/my-quorum-queue
-H "Content-Type: application/json"
-d '{
"durable": true,
"arguments": {
"x-queue-type": "quorum",
"x-quorum-initial-group-size": 3,
"x-delivery-limit": 5,
"x-message-ttl": 86400000
}
}'
Ya da rabbitmqadmin CLI aracıyla:
# rabbitmqadmin ile quorum queue oluştur
rabbitmqadmin declare queue
name=order-processing-queue
durable=true
arguments='{"x-queue-type":"quorum","x-quorum-initial-group-size":3,"x-delivery-limit":10}'
# Kuyruğu listele ve tipini doğrula
rabbitmqadmin list queues name type state members
Önemli argümanlar:
- x-queue-type:
quorumolarak set edilmeli, bu zorunlu - x-quorum-initial-group-size: Başlangıçta kaç replica oluşturulacağı, genellikle cluster büyüklüğüne eşit
- x-delivery-limit: Bir mesaj kaç kez redelivery olabilir, poison message kontrolü için kritik
- x-message-ttl: Mesaj yaşam süresi (millisecond cinsinden)
- x-dead-letter-exchange: Delivery limit dolunca mesajın gideceği exchange
Policy ile Quorum Queue Yönetimi
Production ortamında kuyruğu tek tek argümanlarla oluşturmak yerine policy kullanmak çok daha yönetilebilir bir yapı sunar:
# Tüm "qq-" prefix'li kuyruklara quorum policy uygula
rabbitmqctl set_policy quorum-policy
"^qq-"
'{"x-queue-type":"quorum","x-delivery-limit":10}'
--apply-to queues
--priority 10
# Policy'leri listele
rabbitmqctl list_policies
# Belirli bir vhost için policy oluştur
rabbitmqctl set_policy -p production quorum-policy
"^critical-"
'{"x-queue-type":"quorum","x-quorum-initial-group-size":5,"x-delivery-limit":3}'
--apply-to queues
Klasik Kuyruktan Geçiş Süreci
İşte asıl zorlu kısım burası. Var olan bir klasik kuyruğu doğrudan quorum queue’ya dönüştüremezsin. RabbitMQ bu ikisini tamamen farklı kuyruk tipleri olarak değerlendiriyor. Geçiş için birkaç farklı strateji mevcut.
Strateji 1: Blue-Green Geçiş (Önerilen)
Bu yöntem en güvenli yaklaşım. Önce yeni quorum queue’yu oluşturuyorsun, sonra trafiği yavaş yavaş buraya yönlendiriyorsun.
# 1. Adım: Yeni quorum queue oluştur
rabbitmqadmin declare queue
name=order-queue-v2
durable=true
arguments='{"x-queue-type":"quorum","x-delivery-limit":5}'
# 2. Adım: Exchange binding'i yeni kuyruğa ekle
# (Eski binding'i hemen silme, önce yeni consumer'ları test et)
rabbitmqadmin declare binding
source=order-exchange
destination=order-queue-v2
routing_key=order.new
# 3. Adım: Eski kuyruktaki mesajları boşalt ve izle
rabbitmqadmin get queue=order-queue count=100
# 4. Adım: Eski binding'i kaldır
rabbitmqadmin delete binding
source=order-exchange
destination=order-queue
routing_key=order.new
# 5. Adım: Eski kuyruk boşaldığında sil
rabbitmqadmin delete queue name=order-queue
Strateji 2: Shovel Plugin ile Mesaj Aktarımı
Eğer eski kuyrukta mesajlar birikmiş durumdaysa ve hizmet kesintisi yapamıyorsan, Shovel plugin en iyi arkadaşın olur:
# Shovel plugin'i aktif et
rabbitmq-plugins enable rabbitmq_shovel
rabbitmq-plugins enable rabbitmq_shovel_management
# Dynamic shovel oluştur - mesajları eski kuyruktan yeni quorum queue'ya taşı
rabbitmqctl set_parameter shovel migrate-orders
'{"src-protocol":"amqp091",
"src-uri":"amqp://admin:adminpass@localhost",
"src-queue":"order-queue",
"dest-protocol":"amqp091",
"dest-uri":"amqp://admin:adminpass@localhost",
"dest-queue":"order-queue-v2",
"src-delete-after":"queue-length",
"ack-mode":"on-confirm"}'
# Shovel durumunu izle
rabbitmqctl shovel_status
# Aktarım tamamlandığında shovel'ı kaldır
rabbitmqctl clear_parameter shovel migrate-orders
Dead Letter Queue Yapılandırması
Quorum queue’nun en güçlü özelliklerinden biri, delivery limit aşıldığında mesajları otomatik olarak dead letter exchange’e yönlendirmesi:
# Önce dead letter exchange oluştur
rabbitmqadmin declare exchange
name=dlx-exchange
type=direct
durable=true
# Dead letter queue oluştur (bu klasik queue olabilir, DLQ için quorum şart değil)
rabbitmqadmin declare queue
name=dead-letter-queue
durable=true
# DLX exchange ile dead letter queue'yu bağla
rabbitmqadmin declare binding
source=dlx-exchange
destination=dead-letter-queue
routing_key=failed-messages
# Ana quorum queue'yu DLX konfigürasyonuyla oluştur
curl -u admin:adminpass -X PUT http://localhost:15672/api/queues/%2F/order-queue
-H "Content-Type: application/json"
-d '{
"durable": true,
"arguments": {
"x-queue-type": "quorum",
"x-delivery-limit": 5,
"x-dead-letter-exchange": "dlx-exchange",
"x-dead-letter-routing-key": "failed-messages"
}
}'
Monitoring ve İzleme
Quorum queue’ların sağlığını izlemek için birkaç kritik metric var:
# Kuyruk detaylarını görüntüle
rabbitmqctl list_queues
name
type
state
messages
messages_ready
messages_unacknowledged
leader
members
online
# Quorum queue'lara özel durum bilgisi
rabbitmqctl list_queues
name
type
leader
members
online
--formatter pretty_table 2>/dev/null ||
rabbitmqctl list_queues name type leader members online
# Node başına kuyruk istatistiklerini çek
rabbitmq-diagnostics quorum_status order-queue
# Prometheus endpoint üzerinden metric çek (rabbitmq_prometheus plugin aktifse)
curl -s http://localhost:15692/metrics | grep -E "rabbitmq_queue_messages|rabbitmq_quorum"
Prometheus ve Grafana kullanıyorsan, şu metrikleri mutlaka dashboard’una ekle:
- rabbitmq_quorum_log_commit_latency_seconds: Raft log commit süresi
- rabbitmq_queue_messages_ready: İşlenmeye hazır mesaj sayısı
- rabbitmq_queue_messages_unacked: Acknowledge edilmemiş mesaj sayısı
- rabbitmq_quorum_log_snapshot_chunk_size: Snapshot boyutu
Gerçek Dünya Senaryosu: E-ticaret Sipariş Sistemi
Diyelim ki bir e-ticaret platformunda sipariş işleme sistemini yönetiyorsun. Günlük 100.000 sipariş akıyor, Black Friday’de bu 500.000’e çıkıyor. Mevcut yapında mirrored classic queue kullanıyorsun ve geçen ay node çöküşünde 2.000 siparişi kaybettin. Müşteri şikayetleri, geri ödemeler, itibar kaybı… Şimdi quorum queue’ya geçme zamanı.
Geçiş planın şöyle olabilir:
# 1. Mevcut durumu belgele
rabbitmqctl list_queues name messages consumers durable > queue-snapshot-$(date +%Y%m%d).txt
# 2. Test için yeni quorum queue oluştur
rabbitmqadmin declare queue
name=order-queue-qq
durable=true
arguments='{"x-queue-type":"quorum","x-quorum-initial-group-size":3,"x-delivery-limit":5,"x-dead-letter-exchange":"dlx-exchange"}'
# 3. Canary deployment: Yeni consumer'ları önce %10 trafikle test et
# Application tarafında feature flag ile kontrol et
# 4. Trafiği yavaş artır: %10 -> %25 -> %50 -> %100
# Her aşamada error rate ve latency'yi izle
# 5. Eski kuyruktaki mesajlar bitince shovel ile kalanları taşı
rabbitmqctl set_parameter shovel final-migration
'{"src-protocol":"amqp091",
"src-uri":"amqp://",
"src-queue":"order-queue",
"dest-protocol":"amqp091",
"dest-uri":"amqp://",
"dest-queue":"order-queue-qq",
"src-delete-after":"queue-length",
"ack-mode":"on-confirm",
"src-prefetch-count":100}'
# 6. Migration tamamlandıktan sonra temizle
rabbitmqctl clear_parameter shovel final-migration
rabbitmqadmin delete queue name=order-queue
rabbitmqadmin declare queue
name=order-queue
durable=true
arguments='{"x-queue-type":"quorum","x-delivery-limit":5}'
Performans Tuning
Quorum queue varsayılan ayarlarla iyi çalışır ama production’da birkaç şeyi ayarlamak performansı ciddi artırır:
# rabbitmq.conf dosyasına eklenecek ayarlar
cat >> /etc/rabbitmq/rabbitmq.conf << 'EOF'
# Quorum queue için Raft ayarları
raft.wal_max_size_bytes = 536870912
raft.segment_max_entries = 65536
# Consumer timeout (uzun süreli işler için artır)
consumer_timeout = 1800000
# Disk free space alarm eşiği (quorum queue disk kullanımı yüksek)
disk_free_limit.relative = 2.0
# Channel max
channel_max = 2047
EOF
# Servisi yeniden başlat
systemctl restart rabbitmq-server
# Ayarların uygulandığını doğrula
rabbitmqctl environment | grep raft
Sık Karşılaşılan Sorunlar
Quorum queue minority durumu: Cluster’da 3 node’tan 2’si düşerse, quorum kuyrukları yeni mesaj almayı reddeder. Bu kasıtlı bir davranış, tutarlılık için kullanılabilirliği feda eder.
# Minority durumunu kontrol et
rabbitmqctl list_queues name state leader members online
| grep -v "running"
# Zorla leadership transferi (dikkatli kullan!)
rabbitmqctl quorum_queue force_checkpoint order-queue
Yüksek disk kullanımı: Quorum queue tüm mesajları diske yazar. Segment dosyalarını düzenli compaction ile küçültebilirsin:
# Kuyruk compaction durumunu izle
rabbitmq-diagnostics quorum_status order-queue
# Manuel olarak raft log compaction tetikle
rabbitmqctl eval 'rabbit_quorum_queue:wal_force_roll_over(node()).'
Consumer prefetch ayarı: Quorum queue’larda yüksek prefetch değeri mesaj birikimini engeller ama memory kullanımını artırır. Genellikle 10-50 arası bir değer dengeli çalışır.
Sonuç
Quorum queue’ya geçiş bir gecede olan bir şey değil. Önce test ortamında cluster kur, klasik kuyruk davranışını ve quorum queue davranışını karşılaştır. Node çökme senaryolarını simüle et, mesaj kaybı yaşanmadığını doğrula. Sonra production’da blue-green stratejisiyle yavaş yavaş geçiş yap.
Özetlemek gerekirse:
- Mesaj güvenilirliği kritikse quorum queue zorunlu
- En az 3 node’lu cluster şart, 5 node daha iyi
- Mirrored queue policy’lerini kaldır, quorum queue ile çakışır
- Dead letter queue konfigürasyonunu ihmal etme, poison message sistemleri mahveder
- Monitoring’i geçiş öncesi kur, geçiş sonrası kör uçma
- Disk kapasitesini klasik kuyruğa göre 2-3x fazla planla
RabbitMQ 3.12 ve sonrasında mirrored queue deprecated statüsünde ve bir sonraki major sürümde kaldırılacak. Dolayısıyla bu geçişi ertelemek sadece gelecekte daha büyük bir kriz yaratıyor. Şimdi kontrollü geçiş yapman, ileride zorla yapılacak bir geçişten çok daha az riskli.
