RabbitMQ İle İlk Adımlar

Onur KARAKUŞ
6 min readJun 13, 2021
İmaj adresi : https://www.rabbitmq.com/img/home/banner/webinar/RabbitMQ-Hero-queues-desktop.svg

RabbitMQ’ya bağlanma, kanal ve kuyruk oluşturma, mesajlarımızı gönderip, okuma işlemlerini incelemeye çalıştım. Umarım anlaşılır olmuştur.

Projenin Github bağlantısı aşağıdaki gibidir.
https://github.com/onurkarakus/RabbitMQMessageApplication

Merhaba,

Çocukluğundan kalan bir anı sanırım. Büyüdüğüm zamanlarda artık çok gitmediğim şehrimizde olan fuarlar hep aklımda. Kalabalık olmasının yanı sıra farklı türde ve tarzda bir sürü eğlence yerinin olmasından dolayı seslerin siz gezerken kulağınızda zorlayıcı etkileri. Bir yandan çalan rock müziğin yanında diğer yandan gelen türkü seslerinin karışması. Tabii bunlara eklenen insanların konuşmaları, birbirlerine seslenmeleri ve çocukların neşeli sesleri. Aslında tam bir kaos ortamı. fuar alanından çıktıktan sonra aklınızda kalan tek şey karışıklığın verdiği yorgunluk oluyordu.

Uygulamalarımızda aslında bu şekilde bir yapıya sahip diye düşünüyorum. Bir sürü mesajın düzensiz bir şekilde gönderip alınması ile birlikte ciddi performans sorunlarının oluşması olası. Bu mesajların bu mesajları işleyen yapıların bu işlemlerini asenkron ve sırayla yapmasının sağlamak için de yapılar mevcut. Bunlardan son dönem en çok kullanılanı ise RabbitMQ.

Bir önceki yazımda RabbitMQ hakkında genel bilgileri vermeye ve kurulum işlemlerinin hem OnPremise hem de Docker üzerinde nasıl yapılacağını anlatmaya çalıştım. Bu yazıya aşağıdaki bağlantıdan ulaşabilirsiniz.

Bu yazıda ise C# ile RabbitMQ’yu nasıl kullanacağız? konusunu incelemeye ve sizlere anlatmaya çalışacağım. C# ile iki Console uygulaması oluşturarak birinden gönderdiğimiz mesajların diğer uygulama üzerinden okunmasını sağlayacağız. Böylelikle temel olarak RabbitMQ işleyişini kontrol edebileceğiz. Uygulamamız için bir önceki yazımda anlatmaya çalıştığım Docker kurulumunu yaptığımız RabbitMQ yapısını kullanacağız.

O zaman başlayalım.

İlk önce Visual Studio üzerinden yeni bir Solution dosyası oluşturuyoruz. Daha sonrasında Console uygulamalarımızı bu Solution içerisinde oluşturacağız.

Uygulamalarımız Sender ve Receiver isminde iki console uygulaması olacak. Şimdi ilk olarak Sender uygulamamızı solution içerisinde oluşturalım. Uygulamamızın adı RabbitMQMessageApplication.Sender olsun.

Uygulamamızda RabbitMQ üzerinde oluşturacağımız kuyruğa bir sınıftan oluşturduğumuz nesnemizi göndereceğiz. Bu nesneyi RabbitMQ’ya göndermeden önce de Json ile serileştirmemiz gerekecektir.

Bu işlemleri yapabilmek için uygulamamıza aşağıda bulunan iki Nuget paketini eklememiz gerekmektedir.

Visual Studio içerisine bulunan Nuget Package Manager ile paketlerimizi ekleyebiliriz.

Şimdi uygulamamızı RabbitMQ üzerinde oluşturacağımız bir kuyruğa mesaj göndermesi için kodlarımızı ekleyelim.

İlk önce mesaj nesnemizi tanımlayalım. Bu nesnemiz kuyruğa gönderilecek ve başka bir uygulama üzerinden okunacak olan nesnemiz olacaktır. Sınıf ismini MessageInformation olarak veriyorum.

Daha sonrasında RabbitMQ için tanımları yaptığımız, kuyruk bilgilerini belirlediğimiz ve mesajımızı bu kuyruğa gönderdiğimiz kodları ekliyoruz.

Satır 12 : RabbitMQ bağlantımızı oluşturuyoruz. Burada kurulu olan adresimizi, kullanıcı adımızı ve şifremizi yazmamız yeterli olacaktır.

ConnectionFactory() RabbitMQ host uygulamasına bağlanmak için kullanılır.

Satır 13-14 : Burada RabbitMQ için bağlantımızı ve kanalımızı hazırlıyoruz.

CreateConnection() ConnectionFactory() ile tanımlarını yaptığımız host bağlantımızı oluşturuyor.

CreateModel() RabbitMQ üzerinden yeni bir kanal oluşturmak için kullanılır. Bu kanal sayesinde kuyruk bilgisi oluşturulacak ve mesajımız bu kuyruğa bırakılacaktır.

Satır 16 : Kanal tanımımız üzerinden kuyruk bilgilerimizi giriyoruz ve yeni bir kuyruk oluşturuyoruz.

QueueDeclare() Oluşturduğuz RabbitMQ tanımları içinde bir kuyruk oluşturmamızı sağlayacaktır.

durable : Kuyruğa gönderilecek mesajların saklama yöntemini belirler. Mesajlar InMemory olarak hafızada saklanabilirken istenirse fiziksel olarak da makine içerisinde saklanabilmektedir. Tabii burada hız, performans ve bilgilerin durumu önemli ölçüm değerleri olmaktadır. OnMemory kullanım eğer makine kapanırsa verilerin kaybolacağı anlamına gelmektedir. Bu yüzden kuyruk içinde iletilecek verilerin durumlarına göre bu tanım dikkatli bir şekilde kullanılmalı diye düşünüyorum.

exclusive : Kuyruğun bizim oluşturduğumuz bağlantı haricinde diğer Connectionlar ile de kullanılabileceğini belirler.

autodelete: Eğer kuyrukta bulunan mesaj bilgisini tüm tüketiciler (consumer) almış ise o zaman kuyruğun otomatik olarak silinmesi sağlanır. Yalnız burada dikkat edilmesi gereken konu eğer kuyruk içerisinden bilgiyi alacak bir consumer işlemi iptal edildi veya hata aldı ise o hakkının kaybedecektir. Bunun için autodelete özelliğini kapatıp kuyruk silme işlemi bir metot ile de yapılabilmektedir.

Satır 25 : Mesaj nesnemizi oluşturup gerekli bilgileri dolduruyoruz.

Satır 29 : Mesajımızı serileştirerek kuyruğa gönderilebilecek yapıya getiriyoruz.

Satır 32 : Mesajımızı RabbitMQ üzerinde oluşturduğumuz kuyruğa gönderiyoruz.

BasicPublish() : Hazırladığımız mesajın bir veya daha fazla kuyruğa aktarılmasını sağlar. Bir kuyruk tamam fakat birden fazla kuyruk konusu? Bu işlem için ExchangeType bilgileri kullanılmaktadır. ExchangeType bilgilerinin isimlerini aşağıda bulabilirsiniz. Kendileri ile ilgili yazıları da detaylı bir şekilde araştırdıktan sonra yazmaya çalışacağım.

  • Direct
  • Fanout
  • Headers
  • Topic

Uygulamamızı çalıştırdığımız zaman kullanıcıdan aldığımız mesaj bilgisinin RabbitMQ kuyruğuna gönderildiğini görebilmekteyiz.

Yine aynı şekilde RabbitMQ yönetim paneli içerisinden de kuyruk bilgilerimizi ve bu kuyruk içerisinde bulunan mesajların sayısal bilgilerine ulaşmamız mümkündür. Bunun için http://localhost:1360 adresine gidiyoruz ve guest@guest kullanıcı bilgileri ile login oluyoruz.

Burada da görebileceğiniz gibi MessageTest isminde bir kuyruğumuz ve onun içinde de Ready durumunda bekleyen bir adet mesajımız bulunmaktadır.

O zaman şimdi bu mesajı RabbitMQ üzerinden nasıl okuyacağımıza bakalım. Bunun için yine aynı solution içerisine RabbitMQMessageApplication.Receiver adından yeni bir console uygulaması ekliyoruz.

Projemize RabbitMQ işlemlerini yapabilmek için ve aldığımız mesajları geri açabilmek için aşağıdaki iki paketi Nuget ile ekliyoruz.

Şimdi yapmamız gereken RabbitMQ’ya bağlanarak Sender uygulaması ile oluşturduğumuz ve bir nesnemizi gönderdiğimiz kuyruğa bağlanarak mesajımızı almak. Serileştirilmiş bir şekilde bize gelen bu mesajı açarak artık istediğimiz yerde kullanabileceğiz.

Öncelikle Sender uygulaması içinde kullandığımız sınıfımızı buraya da tanımlayalım. Ortak bir proje içinden de alabilirdik ama benim tembelliğim oldu biraz.

Ardından Receiver uygulamamız için kuyruk bilgisini okuyan kod bloğumuz aşağıdaki gibi olacaktır.

Burada yine Sender uygulamamızdaki gibi ConnectionFactory üzerinden bağlantımızı oluşturduk. Kanal ve kuyruk tanımlarımızı yaptık.

Sender uygulamasından farklı olarak burada farklı olarak Received olayını (event) kullanıyoruz. Bu eventin kullanılma amacı sürekli olarak tanımlarının verdiğimiz kuyruğu dinleyerek yeni mesajların eklenmesi durumunda bu mesajları yakalayabilmektir.

BasicConsume() ile de gelen mesajımızı yakalayabiliriz. Burada kullandığımı autoAck parametresi uygulama içerisinden mesajı okuduktan sonra bu mesajın silinmesini sağlamaktadır.

İlk önce Receiver uygulamasının çalıştıralım ve Sender uygulamasının test ettiğimiz sırada eklediğimiz mesajın kuyruk üzerinden geldiğini görelim.

Şimdi isterseniz hem Sender hem de Receiver uygulamalarını aynı anda çalıştırarak gönderilen mesajın nasıl iletildiği kontrol edelim.

Kuyrukların Silinmesi
Oluşturduğumuz kuyrukların belirli durumlar karşısında silinmesini kendimiz metot kullanarak yapabiliriz. Daha önce de anlatmaya çalıştığım gibi otomatik bir silme mekanizması mevcut fakat bu consumer olan uygulamaların hataları karşısında mesajları almak haklarını kaybetmelerine sebep olabiliyor.

Kuyruk silme işlemini QueueDelete() ile yapabiliyoruz.

queue : Silmek istediğimiz kuyruk adıdır.
ifUnused : Eğer kuyruk kullanılmıyor yani herhangi bir consumer yok ise o zaman silinsin anlamına gelmektedir.
ifEmpty : Eğer kuyruk boş ise silinsin anlamına gelmektedir.

Evet bu yazımda RabbitMQ ile temel işlemlerin nasıl yapılacağı konusunu anlatmaya çalıştım. Umarım açıklayıcı olmuştur.

Bir başka makalede görüşmek üzere.

Kaynaklar :
https://www.rabbitmq.com/documentation.html
https://www.borakasmer.com/rabbitmq-nedir/
https://www.rabbitmq.com/dotnet-api-guide.html

--

--