Spring boot ile RabbitMQ

Merhabalar, yeni bir içerikle bu yazıda sizlerle buluşmaya geldim, en azından benim için yeni olduğunu söyleyebilirim 🙂  RabbitMQ’yu 1 ay önce ilk defa sohbet arasında bir arkadaşımdan duymuştum ilgimi çekti araştırayım nedir ne değildir diye bir anda kendimi bir senaryo üzerinde, rabbitmq ile çalışırken buldum daha sonra dedim ki : ” benim gibi bu alanda yeni olup, hem kendini geliştirmek isteyen hemde sırt çantasına yeni birşey eklemek isteyenlere belki faydam olur öğrendiklerimi paylaşayım . ”  bu amaç doğrultusunda rabbitmq kullanarak bir spring boot uygulaması yazacağız birlikte.

Senaryomuz şu şekilde bir kuyruğumuz var ve bu kuyruğa her 5 sn’de bir çağrı mesajı göndereceğiz ve kuyruğu dinleyip kuyruğa gelen çağrıları konsolda görüntüleyeceğiz .

Bu yazı sonucunda kazancımız, rabbitmq hakkında basic level ‘da bilgi ve bir projeyle tecrübe sahibi olmak ; kuyruğa nasıl message göndereceğimizi producer(üretici) ve bu kuyruğu dinleyerek gelen messageları nasıl consumer(tüketmek) edip process edeceğimizi, öğreneceğiz ve rabbitmq lifecycle’nı anlamış olacağız.

Projeye başlamadan önce bazı kavramları bilmek ve anlamak gerekiyor. Biraz kavramlardan ve çalıştığımız teknoloji nedir ne değildir bahsedelim.

RabbitMQ Nedir ?

RabbitMQ , Message Broker veya Kuyruk Yöneticisi (queue manager) olarak da bilinen bir message kuyruğu(message-queueing ) yazılımıdır . Kuyruk nedir : bir veri yapısı türüdür. örneğin bir mesaj bir yerlere yazılıyor ve o mesajı yazdığımız sırayla tüketebileceğimiz veya bu mesajların sıralamasını konfigüre edebileceğimiz bir mekanizmadır.  Basitçe ifade etmek gerekirse bir yerden aldığı veriyi (Producer) kendine subscribe olan başka bir yere (Consumer)  sırayla teslim etmektedir. Platform bağımsızdır.

Protokol Desteği 

Advanced Message Queuing Protocol (AMQP) ‘den kısaca bahsedecek olursak aslında bir protokoldür. Kuyruk sistemlerinin bir birleriye konuşabilmeleri için gereken protokolun adıdır. Nasıl ki iki veya daha fazla bilgisayarın birbiriyle haberleşmesi içinTCP/IP protokolu var buda onun gibi. Bu protokolle kuyruk tipi farketmeksizin tüm kuyruklarla konuşabiliriz.

Çalışma Mantığı

Sunucu RabbitMQ sunucusuna bir message gönderir ve sunucu bu mesajı ilgili queue’ya yönlendirir.Burada message direkt olarak queue’ye değil exchange üzerinden iletilir. Yani aslında producer  queue’yi bilmemektedir.  Message, exchange üzerinden routing key’e göre “queue” ya iletilmektedir. Sonrasında başka bir uygulama bu queue’yi dinler ve FIFO mantığıyla çalışan kuyruktaki bu messageları consume ederek message’ı process eder ve süreci sonlandırır. Message denilince aklınıza sadece Text gelmesin. Her türlü object’i gönderebiliriz. Örneğin bu uygulamada POJO gönderip alacağız.

PEKİ Neden Kullanılır :  Bankaların kullandığı EFT vb. işlemlerde, yoğun istek (request) alan e-commerce sistemlerinin olmazsa olmazı haline geldi. Sıraya alınan  işlemlerin asenkron bir şekilde yapılması, hem çalışan uygulamanın boş yere bekletilmemesinden hem de sunucu üzerindeki işlem maliyetinin minimuma indirilmesinden dolayı RabbitMQ tercih sebebi olabilir. Ayrıca scalable olmasından dolayı da değişen trafikli yapılarda da tercih edilebilir.

Somut olarak; Postane veya Kargo firması gibi düşünebiliriz.

“Process olarak mektup(nesne) postaneye verilir, postane (kendi iş akışları doğrultusunda) işleme alır ve göndericiye ulaştırır, posta ulaşana kadar siz kendi işlerinizi yapmaya devam edersiniz mektubun gönderilmesini beklemeyiz.”

Part 1: RabbitMQ for beginners - What is RabbitMQ? - CloudAMQP

Bazı kavramlardan bahsedelim:

Producer: Kuyruğa mesaj gönderen veya oluşturan taraftır.

Consumer: Subscribe(abone) olduğu kuyruğa mesaj geldi mi diye dinleyen ve gelen mesajı alıp process edip tüketen taraftır.

Queue:  Mesajların RabbitMQ tarafından eklendiği kuyruktur.

Routing Key : Buraya girdiğimiz key’e göre mesajı ilgili Queue’ye yönlendirir.

Exchange: Producer’dan gelen mesajları kuyruğa iletmek üzere  kabul eder.  Exchange, aldığı mesajla ne yapacağını bilmelidir.  Routing key yardımı ile  mesajı ilgili kuyruğa iletmektedir.

Exchance Type:   Mesajın hangi “queue” ye ne şekilde iletileceğini belirtir. 4 tane exchange tipi bulunmaktadır Direct, Topic, Fanout,Header.

Binding: Exchance ve queue arasındaki bağlantıdır.

Mesajlaşma Mimarileri

point-to-point (Direct Exchange)

Bir mesaj üreticisi tarafından (producer) üretilen mesajın sadece bir tüketiciye (consumer) iletildiği yapıdır. Burada birden fazla tüketici olabilir. Fakat tek bir mesaj sadece tek bir tüketici tarafından işlenir. Direct exchange mesajı gönderdiğiniz key’e göre dağıtıyor  bu yüzden mesaj sadece bir kuyruğa gidiyor.

publish-subscribe (Fanout Exchange)

Bir mesaj üreticisi tarafından üretilen mesajın tüm tüketicilere iletildiği yapıdır.  Bir event oluştuğunda tüm dinleyenler tetikleniyor.  Fanout exchange, gelen mesajı bağlı olan tüm kuyruklara dağıtıyor. Fanout exchange mesajı gönderdiğiniz key’i göz ardı edip, kendisine bağlı olan tüm kuyruklara mesajı iletiyor.

Topic Exchange

Bu exchange tipinde sıradan bir key yapısı kullanamazsınız. Key’inizin belirli özelliklerde olması gerekiyor.  orange.mause, orange.cat ve white.mause şeklinde 3 farklı key’de mesaj üretildiğini düşünün. Bu mesajların nasıl dağıtılacağına ayarlarınıza göre karar veriliyor.

Header Exchange 

Kontrol etmek istediğiniz bilgileri mesajınızın header’ında tanımlayabiliyorsunuz. Topic’te olduğu gibi hem point-to-point hem de publish-subscribe şeklinde davranabiliyorsunuz.

Temel bilgilerden bahsettiğimize göre projeye start verebiliriz.

Ben geliştirme ortamı olarak Intellij  kullanıyorum. Temel sebebi spring-boot projelerini çok rahatlıkla oluşturabilmenizdir. İsterseniz https://start.spring.io adresinden de aynı şekilde bir proje oluşturabilir ve bunu favori geliştirme ortamınıza ekleyebilirsiniz. Build aracı olarak  maven kullanacağım.

Öncelikle yeni bir proje create edelim. Proje tipi olarak maven seçiyorum.

Bir sonraki adıma geçtiğimde proje adını belirliyoruz ve finish diyerek bir proje create etmiş oluyoruz.

RabbitMQ kurulum aşamasına girmeyeceğim. Uygulamada hızlıca kullanmak adına RabbitMQ docker image alarak devam edeceğim. Bilgisayarınızda docker kurulu olduğunu varsayarak devam ediyorum. Projemizde resource dizininin içine docker-compose.yml projesi oluşturalım.

Bu compose dosyası, rabbitmq’yu management arayüzü ile beraber bilgisayarımızda ayağa kaldırmamızı sağlıyor.  Burada dikkat etmemiz gereken nokta portları docker image’ından dış dünyaya açmalıyız. Bu .yml dosyamızı oluşturduktan sonra terminale geliyoruz. Aşağıdaki komutu girerek bilgisayarımızda rabbitmq’yu 5672 portunda ayağa kaldırmış oluyoruz. Burada rabbitmq arayüzünde username ve password ile giriş yapmamız gerekiyor default da username: guest  password: guest  olarak giriş yapabilirsiniz.

Komutu çalıştırdıktan sonra konsolda docker ps komutunu girelim ve rabbitmq docker image ayağa kalkmış mı görelim.

Görüldüğü üzere 5671 portunda rabbitmq docker image ayağa kalkmış .

Browser’a gidelim ve localhost:5671 adresinde rabbitmq management arayüzü geliyor mu bakalım. Benim bilgisayarımda docker,  ip adresi olarak 192.168.99.100 ip adresini kullandığı için 192.168.99.100:5671 adresinde rabbitmq management arayüzünü kullanabiliyorum. Aşağıdaki gibi bir arayüz karşılamalı.

Şimdiye kadar herşey yolunda . pom.xml dosyasını aşağıdaki gibi düzenleyelim.

Şimdi projemize dönelim ve resource dosyasının içine application.properties dosyasını oluşturalım ve aşağıdaki gibi düzenleyelim.

src/main/java dizininin altında bir package olusturalım ben com.aysenur.sr şeklinde oluşturdum. Bu packege’in içine RabbitApplication.java classı’nı olusturalım.

RabbitApplication.java

 

com.aysenur.sr  package’nin içine model package olusturalım ve CalledPerson POJO class’ı  oluşturalım.

Bu class’da nesneyi serialize edip kuyruğa gönderiyoruz almak istediğimiz zamanda java tarafında anlamlı bir sekilde prosess edebilmek için implemente etmeliyiz.  Bunlarla çağrıyı kuyruğa atıcaz kuyruktanda bir baskası alıp process edecek.

CallerPerson.class

Kuyrukta message oluşturabilmek için daha öncede söylediğimize göre Producera ihtiyacımız var. Bunun için bir com.aysenur.sr package’nin içine producer package oluşturup içine CalledPersonProducer.java class oluşturalım. içine kuyruğa message gönderebileceğimiz bir metod yazalım. İlerleyen aşamalarda tekrar buraya döneceğiz.

kuyruktan gelen mesağları dinleyebileceğimiz bir Listener ‘a ihtiyacımız var. com.aysenur.sr içinde yeni bir package oluşturalım listener adında bunun içine de  CallerPersonListener.java sınıfı oluşturalım.

Bir configurasyon sınıfı oluşturalım . Bunu oluşturmamızın amacı bir kuyruk oluştururken kuyruğun adını söylemeliyiz ,  exchange Type’ını belirtmeliyiz vs. bunun gibi configurasyon bilgilerini burada belirleyeceğiz. En başta da söylemiştik örneğimizde DirectExchange type kullanacağınız.

Burada ilk oluşturmamız gereken bir kuyruk ismi bunu birçok yerde kullanacağımız için bir değişken haline getiriyoruz.Bunları ayarlanabilir,değişebilir yapmak içinde application.properties dosyamızda configurasyonları belirlemeliyiz.  Kuyruk ve directExchange’i  bir birlerini ilişkilendirmek için de bir binding oluşturmalıyız.

RabbitMqConfiguration.java

CallerPersonListener.java sınıfına ve CallerPersonProducer.java geri dönelim ve bu classın başına @Service annotation’ınını ekleyelim ki kendi otomatik ayağa kalksın,bir instance oluştursun ben gerektiğinde @Autowired diyip başka bir yerde kullanabileyim. yada producer sınıfında @Bean annotationı ile de initialize edebilirdik.

CallerPersonListener.java sınıfına geri dönelim ve oluşturduğumuz metodun üstüne @RabbitListener annotation’ınını yazalım . Bu annotation kuyruğa message geldiğinde tetiklenecek. Parametre olarak da hangi kuyruğu dinleyeceğini söyleyeceğiz.

CallerPersonProdecer.java sınıfına geri dönelim ve artık message’ı queue’ye gönderelim.

Burada önemli bir nokta  @Scheduled annotation’ını kullanarak kuyruğa bir nevi thread mantığı ile message’ı 5 saniye bekletip tekrar gondermesini sağlayarak en başta senaryomuzda da belirttiğimiz gibi her 5 sn’de bir kuyruğa message gondermeyi  @Scheduled(fixedDelay = 5000, initialDelay = 5000) ile sağlamış oluyoruz.

Uygulamayı run ettiğimizde konsolda aşağıdaki gibi queuetan message alındı bilgisi geliyor ve kuyruğa gönderdiğimiz(producer)  bilgileri kuyruğu dinleyerek ekrana yazdırıyoruz(consumer).

 

RabbitMQ management arayüzüne baktığımızda aşağıdaki gibi görünmektedir.

QUEUES tabına bakarak belirttiğimiz isimde kuyruğumuzun oluşturulduğunu görmemiz mümkün.

Umarım faydalı bir yazı olmuştur. Herhangi bir aklınıza takılan veya yalnış ifade ettiğimi düşündüğünüz bir yer varsa bildirirseniz yorum kısmına sevinirim.. Olumlu veya olumsuz feedbackleri bekliyorum …

Sevgiyle kalın 🙂

Git:  https://github.com/AysenurGokdemir/spring-examples

“Spring boot ile RabbitMQ” üzerine 23 yorum

  1. wonderful publish, very informative. I ponder why the other specialists of this sector
    don’t realize this. You should proceed your writing. I am sure, you’ve a
    great readers’ base already!

  2. I’m extremely pleased to discover this website. I wanted to thank you for ones time just for this fantastic read!! I absolutely enjoyed every part of it and i also have you bookmarked to see new stuff in your site.

  3. Elinize sağlık çok güzel yazı olmuş. Spring boot kafka entegrasyonu ile yazı paylaşabilir misiniz.

    1. Merhaba yazıyı beğenmenize sevindim. talebinizi todo list’ime aldım en kısa zamanda paylaşım gerçekleştireceğim.

  4. Hi there, You’ve done a fantastic job. I will definitely digg
    it and personally recommend to my friends. I’m sure they will be benefited from this website.

  5. Hi, how we can override queue name, exchange and binding properties if we want to use docker-compose file.

  6. It is the best time to make some plans for the future and it is time to be happy.
    I have read this post and if I could I wish to suggest you some interesting things or
    advice. Maybe you can write next articles referring to this
    article. I desire to read even more things about it!

    Also visit my web page :: 바카라검증사이트

Bir Cevap Yazın

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