İLE %100 UYUMLU: Güvenli E-Posta Hosting Hizmetimizi 1 AY ÜCRETSİZ Deneyin! HEMEN OLUŞTURUN
Bir web uygulamasında kullanıcı sipariş verdiğinde yalnızca sipariş kaydının oluşturulması yeterli olmayabilir. Ödeme durumunun güncellenmesi, e-posta gönderilmesi, stok bilgilerinin düzenlenmesi ve raporlama sistemlerinin bilgilendirilmesi de gerekebilir. Bütün bu işlemler aynı isteğin içinde gerçekleştirilirse yanıt süresi uzayabilir ve sistemdeki bir bileşenin yaşadığı sorun diğer işlemleri de etkileyebilir.
RabbitMQ, bu tür durumlarda uygulamalar arasındaki iletişimi düzenlemek için kullanılan bir mesaj aracısıdır (message broker). Uygulamaların birbirlerine doğrudan bağımlı olmadan mesaj göndermesine, işlerin kuyrukta bekletilmesine ve uygun tüketiciler tarafından işlenmesine yardımcı olur.
Ancak RabbitMQ yalnızca mesajları bir yerde tutan basit bir kuyruk sistemi değildir. Mesaj yönlendirme, tüketici onayları, hata yönetimi ve dağıtık uygulamalar arasında iletişim gibi konularda da önemli işlevler sunar.
Bu rehberde RabbitMQ’nun ne olduğunu, nasıl çalıştığını, hangi projelerde kullanıldığını ve güvenilir bir mesajlaşma altyapısı oluşturmak için nelere dikkat edilmesi gerektiğini inceleyeceğiz.
İçindekiler
RabbitMQ, farklı uygulamalar ve servisler arasında mesaj alışverişini sağlayan açık kaynaklı bir mesaj aracısıdır. Uygulamalar mesajları RabbitMQ’ya gönderir, RabbitMQ bu mesajları yapılandırmaya göre ilgili kuyruklara yönlendirir ve tüketici olarak adlandırılan bileşenler mesajları alıp işler.
RabbitMQ, özellikle AMQP protokolüyle tanınır. Bunun yanında uygun yapılandırma ve eklentilerle MQTT ve STOMP gibi farklı protokolleri de destekleyebilir. Desteklenen protokol ve özellikler kullanılan RabbitMQ sürümüne ve yapılandırmasına göre değerlendirilmelidir.
RabbitMQ’nun temel amacı, bir uygulamanın başka bir uygulamanın o anda çalışır durumda olmasına veya işlemi hemen tamamlamasına bağımlı kalmadan iletişim kurabilmesini sağlamaktır.
Örneğin bir e-ticaret uygulaması sipariş oluşturulduğunda e-posta gönderme işini doğrudan gerçekleştirmek yerine RabbitMQ’ya bir mesaj bırakabilir. E-posta servisi bu mesajı daha sonra alıp işleyebilir. Böylece e-posta altyapısında yaşanan geçici bir gecikme, sipariş isteğinin gereksiz yere uzun sürmesini önlemeye yardımcı olur.
RabbitMQ’nun öne çıkan kullanım alanları şunlardır:
Message queue, Türkçede mesaj kuyruğu olarak adlandırılır. Bir uygulamanın gerçekleştirilmesi gereken işi mesaj biçiminde başka bir bileşene iletmesini ve bu işin uygun zamanda işlenmesini sağlayan iletişim yaklaşımıdır.
Bu yapının önemini anlamak için iki farklı senaryo düşünelim.
İlk senaryoda bir kullanıcı rapor oluşturmak ister. Uygulama raporu hazırlamak için onlarca veri kaynağını sorgular, sonuçları birleştirir ve dosyayı oluşturur. İşlem birkaç saniye sürerse kullanıcı isteğin tamamlanmasını bekler.
İkinci senaryoda uygulama rapor hazırlama talebini RabbitMQ üzerinden bir kuyruğa gönderir. İstek kabul edildikten sonra kullanıcıya işlemin başlatıldığı bildirilebilir. Arka planda çalışan bir işçi (worker), kuyruktaki mesajı alır ve raporu oluşturur.
İkinci yaklaşımda uzun süren işlem, kullanıcı isteğinin doğrudan parçası olmaktan çıkar. Uygulama ayrıca ihtiyaç duyulduğunda daha fazla worker çalıştırarak işlem kapasitesini artırabilir.
RabbitMQ kullanmanın başlıca nedenleri şunlardır:
Uygulamalar arasındaki bağımlılığı azaltmak: Mesajı gönderen servis, işi gerçekleştiren servisin iç işleyişini bilmek zorunda değildir.
İş yükünü dengelemek: Gelen görevler kuyrukta birikebilir ve tüketiciler bunları işlem kapasitelerine göre sırayla alabilir.
Geçici sorunları yönetmek: Bir tüketici çalışmadığında, uygun kuyruk ve mesaj kalıcılığı ayarlarıyla işler daha sonra işlenmek üzere bekletilebilir.
Ölçeklenebilirliği desteklemek: İş yükü arttığında aynı kuyruğu tüketen ek worker örnekleri devreye alınabilir.
Bununla birlikte RabbitMQ, bir uygulamanın bütün performans sorunlarını kendiliğinden çözmez. Mesajların nasıl tasarlandığı, tüketicilerin ne kadar hızlı çalıştığı ve kuyrukların nasıl yapılandırıldığı sonuç üzerinde belirleyicidir.
RabbitMQ’nun temel çalışma akışı mesajın gönderilmesi, yönlendirilmesi, kuyrukta tutulması ve bir tüketici tarafından işlenmesi aşamalarından oluşur.
Producer, mesajı RabbitMQ’ya gönderen uygulama veya servis anlamına gelir. Bir web uygulaması, ödeme sistemi ya da arka plan görevi producer olarak çalışabilir.
Örneğin sipariş oluşturulduğunda uygulama, sipariş numarasını ve gerçekleştirilecek işlemin türünü içeren bir mesaj yayınlayabilir.
Mesajların gereksiz kişisel veya hassas bilgiler içermemesi önemlidir. Çoğu durumda mesajda gerekli kayıt kimliğini ve işlem türünü bulundurmak, diğer bilgileri ihtiyaç anında güvenilir veri kaynağından okumak daha uygun olabilir.
RabbitMQ’da AMQP 0-9-1 kullanıldığında producer mesajı doğrudan kuyruğa göndermek yerine genellikle bir exchange’e yayınlar. Exchange, mesajın hangi kuyruğa veya kuyruklara yönlendirileceğini belirleyen kuralları uygular.
Bu ayrım, mesaj gönderen uygulamanın belirli bir tüketici kuyruğuna doğrudan bağımlı olmasını önlemeye yardımcı olur.
RabbitMQ’da yaygın olarak kullanılan dört exchange türü bulunur:
Örneğin order.created anahtarını kullanan bir mesaj, sipariş olayları için tanımlanmış uygun kuyruklara yönlendirilebilir. Böylece farklı servisler yalnızca ilgilendikleri olayları tüketebilir.
order.created
Kuyruk, yönlendirilen mesajların tüketiciler tarafından alınana kadar bekleyebildiği yapıdır. Tüketicinin işlem kapasitesi gelen mesaj sayısından düşükse kuyrukta birikme meydana gelebilir.
Bu birikme her zaman hata anlamına gelmez. Kısa süreli yoğunluklarda kuyruk, uygulamanın gelen iş yükünü daha sonra işleyebilmesine yardımcı olur. Ancak kuyruk sürekli büyüyorsa tüketici kapasitesi, mesaj üretim hızı veya işleme süresi incelenmelidir.
Kuyruklar dayanıklılık, mesajların saklanma süresi ve kapasite sınırları gibi ihtiyaçlara göre yapılandırılabilir.
Consumer, kuyruktan mesaj alan ve mesajın temsil ettiği işi gerçekleştiren bileşendir. Mesajı aldıktan sonra bir veritabanı kaydı oluşturabilir, e-posta gönderebilir veya başka bir servise istek yapabilir.
İşlem başarıyla tamamlandığında tüketici, uygun onay mekanizmasıyla RabbitMQ’ya mesajın işlendiğini bildirebilir. Hata durumunda ise mesajın yeniden kuyruğa alınması veya başka bir yere yönlendirilmesi tercih edilebilir.
Bu süreç, mesajların yalnızca iletilmesini değil, işlenme durumlarının da kontrollü biçimde yönetilmesini sağlar.
RabbitMQ, özellikle uzun süren görevlerin kullanıcı isteklerinden ayrılması veya birden fazla servisin olaylar üzerinden iletişim kurması gereken uygulamalarda kullanışlıdır.
Dosya dönüştürme, rapor hazırlama, görsel işleme ve toplu veri aktarımı gibi işlemler bir mesaj kuyruğuna bırakılabilir.
Örneğin kullanıcı büyük bir rapor talep ettiğinde uygulama hemen raporun hazır olmasını beklemek yerine görevi kuyruğa ekleyebilir. Worker işlemi tamamladığında uygulama raporun durumunu güncelleyebilir.
Toplu bildirim gönderen uygulamalarda mesaj kuyruğu, gönderim işlerinin kontrol altında tutulmasına yardımcı olur. Bildirim servisinin geçici olarak yavaşlaması durumunda görevler uygun yapılandırmayla kuyrukta bekleyebilir.
Böylece uygulamanın her istekte harici bir e-posta sistemini beklemesi gerekmez. Bununla birlikte tekrar deneme politikası dikkatli tasarlanmalıdır; aksi hâlde aynı bildirimin birden fazla kez gönderilmesi mümkündür.
Mikroservislerde farklı işlevler ayrı uygulamalar tarafından yürütülebilir. Sipariş, stok, bildirim ve raporlama servisleri birbirleriyle mesajlar üzerinden iletişim kurabilir.
Örneğin sipariş oluşturulduğunda bir olay yayınlanabilir. Stok servisi bu olayı alarak ilgili ürünün stok durumunu güncelleyebilir. Bildirim servisi de aynı olaydan haberdar olarak kullanıcıya bilgi verebilir.
Bu yaklaşım servisler arasındaki doğrudan bağlantıyı azaltır. Ancak olayların sırası, tekrar teslimat ve başarısız işlemlerin yönetimi ayrıca tasarlanmalıdır.
RabbitMQ, uygulamalar arasında düşük gecikmeli mesaj iletimi gereken bazı sistemlerde de kullanılabilir. Sensörlerden gelen olaylar, uygulama içi bildirimler veya işlem durumları uygun tüketicilere yönlendirilebilir.
Bununla birlikte çok uzun süreli olay geçmişinin tutulması, çok büyük hacimli akışların tekrar tekrar okunması veya olayların farklı tüketiciler tarafından bağımsız biçimde baştan sona taranması gerekiyorsa RabbitMQ Streams ya da Apache Kafka gibi alternatifler de değerlendirilmelidir.
Mesajlaşma altyapısında önemli olan yalnızca mesajı hızlı göndermek değildir. Uygulama veya ağ hatası meydana geldiğinde mesajın kaybolup kaybolmayacağı ve işlemin tekrar denenip denenmeyeceği de belirlenmelidir.
Acknowledgement, tüketicinin mesajın işlendiğini RabbitMQ’ya bildirmesidir. Manuel onay kullanıldığında mesaj, tüketici başarılı işlemi tamamlayıp onay verene kadar tamamlanmış kabul edilmez.
Tüketici onay vermeden bağlantısını kaybederse RabbitMQ, ilgili mesajı yeniden teslim edebilir. Bu davranış mesajın kaybolma riskini azaltır ancak aynı mesajın birden fazla kez işlenmesine neden olabilir.
Bu nedenle tüketiciler mümkün olduğunca idempotent tasarlanmalıdır. İdempotent işlem, aynı mesaj birden fazla kez işlense bile sistemde istenmeyen tekrar sonuçlarının oluşmasını önler. Örneğin sipariş numarasını kontrol ederek aynı sipariş için ikinci kez işlem yapılmasını engellemek bu yaklaşımın bir örneğidir.
Mesajı gönderen uygulama, veriyi ağ üzerinden iletmiş olmasını mesajın RabbitMQ tarafından güvenli biçimde kabul edildiğinin kanıtı olarak görmemelidir.
Publisher confirms, broker’ın mesajı kabul ettiğini producer’a bildiren mekanizmadır. Özellikle önemli mesajların kaybolma riskini azaltmak için kalıcı mesajlar, dayanıklı kuyruklar ve publisher confirms birlikte değerlendirilmelidir.
Bu mekanizmalar tek başına uygulamanın bütün iş akışını garanti altına almaz. Mesajın bir veritabanı işlemiyle birlikte üretilmesi gerekiyorsa veritabanı ile mesaj broker’ı arasındaki tutarlılık da tasarlanmalıdır. Transactional outbox gibi yaklaşımlar bu sorunun çözümünde kullanılabilir.
Bir mesaj sürekli başarısız oluyorsa onu sınırsız biçimde aynı kuyruğa geri göndermek sorun yaratabilir. Bu durum tüketicinin aynı mesajı tekrar tekrar işlemesine ve kaynakların boşa harcanmasına yol açabilir.
Dead Letter Exchange (DLX), belirli koşullarda işlenemeyen veya reddedilen mesajların ayrı bir hedefe yönlendirilmesini sağlayabilir. Böylece başarısız mesajlar daha sonra incelenebilir.
Tekrar denemeler için gecikme ve deneme sayısı sınırları belirlemek, kalıcı hatalarla geçici hataları ayırt etmek önemlidir. Hatalı veri içeren bir mesajın tekrar tekrar denenmesi çoğunlukla sorunu çözmez.
RabbitMQ kullanan bir sistemin yük arttığında nasıl davranacağı önceden planlanmalıdır.
Aynı kuyruğu birden fazla tüketici işleyebilir. Böylece görevler uygun tüketicilere dağıtılır ve toplam işleme kapasitesi artırılabilir.
Ancak tüketici sayısını artırmak her zaman doğrusal performans artışı sağlamaz. İşlemler aynı veritabanına yoğun biçimde yazıyorsa darboğaz mesaj broker’ından çok veritabanında oluşabilir. Worker sayısı, gerçek iş yüküyle test edilerek belirlenmelidir.
Dayanıklı kuyruk (durable queue), kuyruk tanımının broker yeniden başlatıldığında korunmasına yardımcı olur. Kalıcı mesajlar (persistent messages) ise mesaj verisinin yeniden başlatma sonrasında korunmasına yönelik davranışı destekler.
Bu iki özellik farklı şeyleri ifade eder. Dayanıklı bir kuyruğa geçici mesajlar göndermek, mesajların aynı kalıcılık beklentisini taşıdığı anlamına gelmez. Önemli mesajlarda uygun kuyruk türü, kalıcı mesaj ayarları ve publisher confirms birlikte ele alınmalıdır.
Quorum queue, mesaj verisini birden fazla RabbitMQ düğümüne çoğaltarak dayanıklılığı artırmayı amaçlayan kuyruk türüdür. Bir düğümün arızalanması durumunda uygun çoğunluk ve erişilebilirlik koşulları sağlanıyorsa kuyruk çalışmaya devam edebilir.
Bu yapı daha yüksek veri güvenliği sağlayabilir ancak kaynak kullanımı ve gecikme açısından maliyeti vardır. Her geçici kuyruk veya düşük gecikme gerektiren senaryo için en uygun seçenek olmayabilir.
Yüksek erişilebilirlik planlamasında yalnızca kuyruk türü değil, düğümlerin yerleşimi, ağ bağlantıları, disk kapasitesi, izleme ve kurtarma prosedürleri de dikkate alınmalıdır.
RabbitMQ ve Apache Kafka, mesajlaşma ve olay tabanlı mimarilerde kullanılabilen teknolojilerdir; ancak temel kullanım modelleri farklılaşır.
RabbitMQ, mesajların kuyruklara yönlendirilmesi, görevlerin tüketicilere dağıtılması ve farklı mesajlaşma desenlerinin uygulanması konusunda güçlü seçenekler sunar. Arka plan görevleri, servisler arası iletişim ve yönlendirme kurallarının önemli olduğu sistemlerde tercih edilebilir.
Kafka ise kalıcı olay akışları, yüksek hacimli veri akışı ve olayların belirli süre boyunca saklanarak tüketiciler tarafından yeniden okunabilmesi gereken mimarilerde öne çıkar.
Temel farkları şöyle özetleyebiliriz:
Bu karşılaştırma, bir teknolojinin diğerinden her durumda daha iyi olduğu anlamına gelmez. Doğru seçim; mesajların ne kadar süre saklanacağına, tüketicilerin mesajları nasıl işleyeceğine, veri hacmine ve sistemin hata toleransı gereksinimlerine bağlıdır.
RabbitMQ’nun sağlıklı çalışması için bazı tasarım hatalarından kaçınmak gerekir.
Mesajları sınırsız biçimde kuyrukta biriktirmek: Tüketiciler yavaşladığında kuyruk uzunluğu artabilir. Kuyruk sınırları, disk kapasitesi ve alarm eşikleri belirlenmelidir.
Mesajı işlem tamamlanmadan onaylamak: Tüketici mesajı aldıktan hemen sonra onay verir ve işlem tamamlanmadan kapanırsa iş kaybolabilir. Onay zamanı, uygulamanın iş mantığına uygun seçilmelidir.
Tekrar teslimatı hesaba katmamak: Bir mesaj birden fazla kez teslim edilebilir. Tüketici işlemleri tekrar çalıştırıldığında çift kayıt veya yinelenen bildirim oluşturmamalıdır.
Hata durumunda sürekli yeniden kuyruğa almak: Kalıcı bir hatayı tekrar denemek sorunu çözmeyebilir. Sınırlı tekrar denemeleri ve DLX gibi mekanizmalar değerlendirilmelidir.
İzleme yapmamak: Kuyruk uzunluğu, mesaj işleme süresi, tüketici sayısı, bellek, disk kullanımı ve bağlantı hataları takip edilmelidir. Böylece kapasite sorunları büyümeden fark edilebilir.
RabbitMQ, uygulamalar arasında güvenilir ve esnek mesajlaşma kurmak isteyen geliştiriciler için önemli bir altyapı bileşenidir. Arka plan görevlerini yönetmek, yoğun iş yükünü worker’lara dağıtmak, servisler arasındaki bağımlılığı azaltmak ve başarısız mesajları kontrollü biçimde ele almak için kullanılabilir.
Bununla birlikte başarılı bir mesajlaşma mimarisi yalnızca RabbitMQ kurmaktan ibaret değildir. Mesajların kalıcılığı, tüketici onayları, tekrar teslimat, idempotent işlem tasarımı, hata kuyruğu ve kapasite takibi birlikte düşünülmelidir.
Bir projede RabbitMQ kullanmayı planlıyorsanız öncelikle hangi işlemlerin kullanıcı isteğinden ayrılması gerektiğini ve hangi servislerin birbirleriyle mesajlaşacağını belirleyin. Ardından beklenen mesaj hacmini, hata senaryolarını ve veri kaybına ilişkin gereksinimleri değerlendirin. Bu yaklaşım, gereksiz karmaşıklık oluşturmadan sürdürülebilir bir mesajlaşma altyapısı kurmanıza yardımcı olur.