Derinlemesine yazılım eğitimleri için kanalımı takip edebilirsiniz...

RabbitMQ – Akıllı Kuyruk Mimarisi Nasıl Tasarlanır?

Merhaba,

Bir önceki RabbitMQ – Basitçe Kuyruğa Mesaj Gönderme ve Okuma başlıklı yazımda RabbitMQ servisine mesaj gönderme ve gönderilen mesajları okuma eylemlerini temel düzeyde incelemiş bulunmaktayız. Bu içeriğimizde ise kuyruk mimarisini daha da akıllı hale nasıl getirebileceğimizi orta şeker bir gerçek hayat projesi üzerinden konuşacağız.

Akıllı Kuyruk Mimarisi Nedir?

Bir kuyruk mimarisinin akıllı olabilmesi için, (1)edindiği mesajların güvenli bir şekilde tutulup, (2)eşit bir dağılımla tüketilmesi ve tüm bu işlemler neticesinde sunucunun (3)mesajın işlendiğine dair haberdar edilmesi gerekmektedir. İşte böyle bir yapılanma akıllı kuyruk mimarisi olarak nitelendirilebilmektedir.

Bu açıklamadan çıkardığımız sonuç şudur ki bir kuyruk yapısının akıllı olabilmesi için aşağıdaki özellikleri uyguluyor olması gerekmektedir.

  • Mesajların Dayanıklılığı(Message Durability)

    (1)…edindiği mesajların güvenli bir şekilde tutulup…

    RabbitMQ instance’ına gönderilen mesajların güvenliğini sağlayarak olası restart durumlarında kalıcılığı korumak için Publisher ilgili mesajı göndermeden önce mesaj güvenirliliğini sağlamalıdır.

            static void Main(string[] args)
            {
                ConnectionFactory factory = new ConnectionFactory();
                factory.Uri = new Uri("amqp://hkhjerrt:hcqiavAqll6-co4abXnSqUBh_hHifz-Z@hornet.rmq.cloudamqp.com/hkhjerrt");
    
                using (IConnection connection = factory.CreateConnection())
                using (IModel channel = connection.CreateModel())
                {
                    channel.QueueDeclare("iskuyrugu", durable: true, false, false, null);
                    for (int i = 1; i <= 100; i++)
                    {
                        byte[] bytemessage = Encoding.UTF8.GetBytes($"is - {i}");
    
                        IBasicProperties properties = channel.CreateBasicProperties();
                        properties.Persistent = true;
    
                        channel.BasicPublish(exchange: "", routingKey: "iskuyrugu", basicProperties: properties, body: bytemessage);
                    }
                }
            }
    

    Bunun için yukarıdaki kod bloğundaki 9. satırda olduğu gibi ‘durable’ parametresi true olarak ayarlanır ve tanımlanan kuyruk sağlamlaştırılır. Ayriyetten 14 – 15. satırlar arasında bir ‘IBasicProperties’ türünden nesne oluşturulur ve Persistent özelliğine true değeri atanarak RabbitMQ’da fiziksel kayda alınır ve kalıcılığı sağlanır. Böylece mesaj güvenliğide sağlamlaştırılmış olur. 17. satırda ise ‘basicProperties’ parametresine ilgili property verilerek mesajımız güvenli bir şekilde kuyruğa gönderilir.

  • Eşit Dağılım(Fair Dispatch)

    …(2)eşit bir dağılımla tüketilmesi…

    Bir kuyruğu tüketmek için birden fazla consumer olabilir. Böyle bir durumda tüm consumerlara mesajlar eşit dağıtılmalıdır. Aksi taktirde işlemci gücü vs. gibi donanımsal özellikleri daha ağır basan consumerlar kısa zamanda çok mesaj işleyebildikleri için daha yoğun çalışmak zorunda kalabilirler.

    Consumer;

            static void Main(string[] args)
            {
                ConnectionFactory factory = new ConnectionFactory();
                factory.Uri = new Uri("amqp://hkhjerrt:hcqiavAqll6-co4abXnSqUBh_hHifz-Z@hornet.rmq.cloudamqp.com/hkhjerrt");
    
                using (IConnection connection = factory.CreateConnection())
                using (IModel channel = connection.CreateModel())
                {
                    channel.QueueDeclare("iskuyrugu", durable: true, false, false, null);
                    channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);
    
                    EventingBasicConsumer consumer = new EventingBasicConsumer(channel);
                    channel.BasicConsume("iskuyrugu", false, consumer);
                    consumer.Received += (sender, e) =>
                    {
                        Thread.Sleep(int.Parse(args[0]));
                        Console.WriteLine(Encoding.UTF8.GetString(e.Body) + " alındı");
                        channel.BasicAck(e.DeliveryTag, false);
                    };
                    Console.Read();
                }
            }
    

    Yukarıdaki örnek kod bloğunda bir consumer çalışması yapılmıştır. 10. satıra göz atarsanız eğer ‘BasicQos’ metodu ile port önceliği anlamına gelen QoS servisi ile consumer önceliği eşitlenmekte ve böylece eşit dağılım sağlanmaktadır.

    ‘BasicQos’ metodunun;

    • prefetchSize parametresi : Mesaj boyutunu ifade eder. 0(sıfır) diyerek ilgilenmediğimizi belirtiyoruz.
    • prefetchCount parametresi : Dağıtım adetini ifade eder.
    • global parametresi : true ise, tüm consumerların aynı anda prefetchCount parametresinde belirtilen değer kadar mesaj tüketebileceğini ifade eder. false değeri ise, her bir consumerın bir işleme süresinde diğer consumerlardan bağımsız bir şekilde kaç mesaj alıp işleyeceğini belirtir.
  • Mesajların Alındı Haberi(Message Acknowledgement)

    …(3)mesajın işlendiğine dair haberdar edilmesi…

    Kuyruktaki mesaj consumer tarafından başarıyla işlendikten sonra sunucu bilgilendirilmelidir. Yukarıda “Eşit Dağılım”a verilen örnek kod bloğundaki 18. satırda ‘BasicAck’ fonksiyonu ile bu işlemi gerçekleştirerek kuyruktan mesajın silinmesi sağlanmaktadır.

Test Edelim

Yukarıdaki yaptığımız çalışmaya dikkat ederseniz, publisher her çalıştırıldığında 100 adet mesajı kuyruğa iletmekte ve bunun yanında consumer ise ayağa kaldırılırken gönderilen argümandaki sayısal değer kadar süreci durdurarak işlemektedir. Dolayısıyla bu inşa neticesinde aşağıdaki görselde olduğu gibi anlamlı bir kuyruk mimarisinin neticesiyle karşılaşmaktayız.
RabbitMQ - Akıllı Kuyruk Mimarisi Nasıl Tasarlanır?
Görüldüğü üzere her bir consumer verilen değer kadar saniye aralığında bir mesaj tüketmektedir.

Vee böylece bir RabbitMQ servisini kullanan uygulamada akıllı kuyruk mimarisinin nasıl ve nelere dikkat edilerek tasarlandığını incelemiş ve örneklendirmiş olduk. Vakit ayırıp okuduğunuz için teşekkür ederim 🙂

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar…

Not : Örnek uygulamayı indirmek için buraya tıklayınız.

Bunlar da hoşunuza gidebilir...

9 Cevaplar

  1. baran dedi ki:

    Hocam merhabalar, BasicConsume ile BasicAck metodlarının farkını ben tam olarak kavrayamadım. İkisi de mesajın okunduğunu bildirmiyor mu uygulamaya? Bazı örneklerer baktığımda 2 si de kullanılıyor aynı anda bazen sadece 1 tanesi. Neye göre dğeişiyor?

  2. Özgür dedi ki:

    Hocam RabbitMQ ile Microservis mimarisinde transaction yönetimi ve microservisler arası kullanımına yönelik ufak da olsa bir adet reel hayat örneği paylaşır mısınız ? Desteğiniz için teşekkürler…

  3. serdar alper dedi ki:

    console dan nasıl cıkacak otomatik olarak 🙂

  4. Ahmet Kandil dedi ki:

    Merhaba hocam Persistent ve Durable ikiside verilerin fiziksel diskte saklanıp kaybolmamasını sağlıyor. Arasında bir fark var mı ?

    • Gençay dedi ki:

      Merhaba Ahmet,

      RabbitMQ’da Persistent ve Durable sıklıkla karıştırılan kavramlardır. Halbuki bu iki kavramı birbirinden ayırabilmek oldukça kolaydır.

      Her iki kavramı açıklamaya gelmeden önce ilk olarak şöyle bir temelle başlayalım;

      Mesajlar gibi kuyruklarda kalıcı olabilirler…

      Bu temel eşliğinde kavramları açıklarsak eğer, Persistent mesajların kalıcılığını ifade etmektedir. Yani bir mesajın fiziksel olarak kaydedilmesidir. RabbitMQ herhangi bir sebepten dolayı yeniden başlatılırsa eğer kalıcı olan mesajların dışındakiler kaybolacaktır. Benzer şekilde Durable ise kuyrukların dayanıklılığını bir başka deyişle kalıcılığını ifade eder. Bu da kuyrukların fiziksel olarak kaydedilmesi demektir. Böyle bir durumda RabbitMQ yine herhangi bir sebepten dolayı yeniden başlarsa eğer kalıcı olan kuyruklar ve içlerindeki mesajlarla birlikte kalan sağlar bizimdir demektir.

      Sonuç itibariyle, mesajlar kuyrukların içlerinde olan veriler olduğundan dolayı kalıcılığı sağlayabilmek için her iki özelliğinde aktif olması gerekmektedir. Nihayetinde Persistent olan bir mesaj Durable olmayan bir kuyrukta ise her ne kadar kalıcılık özelliği gösterse de kuyruk kalıcı olmadığından dolayı silinecektir. Benzer mantıkla, Durable olan bir kuyruk içerisinde Persistent olmayan mesaj da aynı şekilde olası kapanmalarda kalıcılık göstermeyecek ve silinecektir.

      Faydalanmanız dileğiyle…
      Sevgiler…

  5. batuhan dedi ki:

    mvc web uygulamasının home index get methodunda deneyeyim dedim de bende sadece 1 tane alıyor ve hep aynısını alıyor.

  1. 29 Şubat 2020

    […] RabbitMQ – Akıllı Kuyruk Mimarisi Nasıl Tasarlanır? […]

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir