WorkQueue

526

Mesaj kuyruklarını, task işleyecek şekilde de kullanabiliriz. WorkQueue, işlenmesi uzun süre alan işlerin bir mesaj gibi queue içerisine konması yaklaşımıdır. Genellikle, sistem kaynaklarını fazla tüketen işlemler ve özellikler web uygulamalarında kullanılır. Örneğin, yeniden ölçeklemesi yapılacak resim dosyaları veya pdf dosya üretimlerinde, Consumer uygulamalar başka bir sunucuda çalıştırılarak, web sunucusunun bu işlemlerden etkilenmesinin önüne geçilir.

Queue’ya eklenen işlerin çoklu consumerlara dağıtımı rabbitmq tarafından yapılır. Yük dağılımı rabbitmq sorumluluğundadır. Biz sadece producer ve consumer uygulamaları yazarız.

RabbitMQ’ya yabancı iseniz, Merhaba RabbitMQ makalemizi incelemenizi öneririm.

Bu makalemizde yapacaklarımız sırası ile;

1* Producer ve Consumer uygulamaları geliştireceğiz.
2* Producer uygulamamız farklı sayıda * işaretinden oluşan işler gönderecek(*,***,**).
3* Consumer uygulamamız mesajdaki her bir * için 1 saniye bekleyecek. Bu sayede, farklı süreler alan işleri simule etmiş olacağız.

Producer uygulamamız:

ProducerWQ isimli bir java projesi oluşturalım. Projemizi maven uyumlu hale getirelim.

pom.xml:

SenderStater.java:

Consumer uygulamamız:

ConsumerWQ isimli bir java projesi oluşturalım. Projemizi maven uyumlu hale getirelim.

pom.xml:

ReceiverStarter.java:

Uygulamalarımız geliştirdikten sonra her iki uygulamızdan birer jar dosyası oluşturuyoruz. Sonra istediğimiz bir klasöre bu jarlarımı ve ayrıca amqp-client-4.0.1.jar ile slf4j-api-1.7.21.jar dosyalarını koyuyoruz. Bu iki jar dosyasını $USER-HOME/.m2/repository altında bulabilirsiniz. Klasörün içeriği aşağıdaki gibi olmalı.

Artık uygulamamalarımızı çalıştırabiliriz. Komut satırından çalıştıracağız. Test için çalışan iki adet Consumer bir adet Producer uygulaması olması lazım. Üç tane terminal ekranı açalım. Jar klasörüne gidelim. Klasörün içerisinden çalıştırıcağız.

İki terminale aşağıdaki komutu kopyalayalım.

Üçüncü terminale de takip eden komutu kopyalayalım.

Önce consumer komutları sonrasında producer komutun çalıştıralım. Terminalllerde aşağıdaki çıktılar yazmalı.

Çıktılardan da görebileceğimiz gibi, queue’dan tasklar sıra ile Consumer’lara gönderildi.
1nci task: *
2nci task: *****
3ncü task: **
4ncü task: ***

1nci ve 3ncü tasklar bir consumera, diğer iki task ise diğer consumera gönderildi. İşin bitip bitmemesi kontrol edilmiyor. Bu mesaj dağıtım modeline round-robin denir. Bizim istediğimiz ise, Consumer’ların idle kalmaması. Bunun için;
channed.basicQos(int i) metotunu autoAck değerini false yaparak kullanıyoruz. Bu cümle burada dursun, biz Message Acknowledgement ne demek ona bakalım.

Message Acknowledgement:
Acknowledgement’ın alındı bildirimi, onay gibi anlamları vardır. Acknowledge, rabbitmq ya özgü bir durum değildir. İki farklı uygulamanın konuşturulduğu mimarilerde, ack mesajı gerekli durumlarda kullanılır. Biz uygulamamızı autoAck = true olarak geliştirdik. Queue mesaj’ı gönderdi ve peşinden sildi. Mesajların işlenip işlenmemesi önemli olmadığı durumlar da bu yapı kullanılabilir. Ama workqueue gibi task gönderdiğimiz durumda dahil olmak üzere, bir çok uygulamada mesajların işlenmesi çok önemlidir. Consumer’ın herhangi bir anda çalışmıyor olma durumunda (Channel kapanması veya TCP bağlantısının kopma durumu) Consumer’ın aldığı mesajın başka bir Consumer’a gönderilebilmesi için autoAck = false olarak çalışmalıyız.
AutoAck false olduğunda, eğer Consumer’dan ack mesajı gelmez ise, mesaj tekrardan queue’ya eklenir ve başka bir Consumer bağlı ise, ona gönderilir.

basicConsume() metotunun ikinci parametresi autoAck parametresini alır. Sanırım şimdi yukarıdaki cümlemiz daha anlamlı oldu sanırım.

ReceiverStarter.java sınıfımızı aşağıdaki gibi düzenleyelim.

Consumer uygulamasından yeni bir jar oluşturup uygulamalarımızı daha önceki sıra ile çalıştırdığımızda aşağıdaki sonucu alırız.

Gördüğümüz gibi, taskları verimli bir şekilde Consumer’lara gönderdik.

Ack mesajı kullandığımız yapıda her zaman mesaj kaybolmasının önüne geçemez. RabbitMQ eğer bir şekilde kapanır ise, queue içerisindeki mesajlar kaybolur. Bunu engellemek için hem queue’yu hem de mesajımızı kalıcı(durable) olarak etiketlemeliyiz.

queueDeclare metotunun ikinci parametresi kalıcılık parametresidir. basicPublish metotunun ikinci parametreside mesaj için kalıcılık parametresidir. Bunlar kalıcı olarak set edildiğinde, mesaj queue’ya gönderildikten sonra hem queue’ya eklenir hem diske yazılır. Bu şekilde rabbitMQ kapansa bile diskte yazılan mesajlar kaybolmaz.

NOT: RabbitMQ da tanımladığımız bir queue’nun özellikleri daha sonra güncellenemez. Biz önceki örneklerimizde kullanıdığımız MERHABA isimli queue’yu durable false olarak tanımlamıştık, şuan aynı queue’yu kullanamayız.

SenderStarter.java:

ReceiverStarter.java

Her iki jar dosyamızı güncelledik. Producer uygulamamızı çalıştırdık. Ardından queue’ları listeledik.

 

RabbitMQ’yu stop start edip tekrardan queue listeleme komutunu çalıştırdık.

DURABLE isimli queue’nun ve içindeki mesajların kalıcı olduğunu gördük.

Şimdilik bu kadar. İnşallah faydalı olmuştur.

İyi Çalışmalar

ÖrnekProje

Yorum yaz

Email adresiniz yayınlanmayacaktır.