14 Aralık 2017 Perşembe

RabbitMQ C++ ve Python uygulamaları

RabbitMQ, kendi sitesindeki ifadeye göre en yaygın kullanılan açık kaynak mesaj aracısıdır. Birçok işletim sisteminde ve popüler tüm programlama dillerinde çalışabilir. Faklı uygulamalar arasında asenkron iletişim kurulmasını sağlar. ApacheQPid, ActiveMQ, ZeroMQ gibi farklı alternatif sistemler olduğunu da belirtelim. Temel mantık şu şekildedir: Bir üretici(producer) iletilecek mesajı örneğin postayı kargo firmasına bırakır. Kargo firması yani RabbitMQ ise bu mesajın ilgili alıcı(consumer) tarafından alınmasını sağlar. 


RabbitMQ terimler ;
  • Producer: mesajı gönderen uygulamadır
  • Queue : Gönderilen mesajlar kuyrukta sıralanır ve alıcıya bu kuyruktan iletilir. 
  • Consumer: Kuyruktan mesajları okuyan uygulamadır.

Bu yazı kapsamında RabbitMQ nun C++ ve Python ile kullanılmasına dair örnekler paylaşacağım. Bunun için kullanacağımız kütüphaneler  SimpleAmqpClient  ve pika.  SimpleAmqpClient kurulumunu en kolay şekilde (Visual Studio kullanıyorsanız şayet) NuGet Package Manager ile gerçekleştirebilirsiniz. Böylece gerekli boost chrono ve boost system kütüphaneleri de otomatik olarak projenize dahil edilir. Python için pika kurulumu ise, terminalden  pip install pika komutu ile kolayca gerçekleştirilir.




İlk olarak Python ile RabbitMQ sunucumuzda mesaj oluşturan üretici(producer) uygulamamızı yazalım.

Python ile RabbitMQ producer
( i=0 baslangıç değeri atanmış bir değişken olsun )
import pika
 
i=i+1
message = str(i)+". mesaj!"
          
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
 
channel.queue_declare(queue='kuyruk1')
 
# yukarıda aldığımız kanala bir iş gönderiyoruz
channel.basic_publish(exchange='',
                      routing_key='kuyruk1',
                      body=message)
 
print(message + " mesajı sıraya gönderildi.")
 
connection.close()

Artık her çalıştırmada 1.mesaj, 2.mesaj .... şeklinde mesajları "kuyruk1" isimli kuyruğa  gönderecek bir producer.py dosyamız mevcut. Bu dosyayı 5 defa çalıştırdığımızda RabbitMQ sunucusundaki "kuyruk1" isimli kuyrukta 5 mesaj birikecektir. Şimdi ise bu mesajları okuyacak C++ consumer(tüketici) uygulamasını yazalım.
#include<iostream>

#include <SimpleAmqpClient/SimpleAmqpClient.h>

int main()
{

 AmqpClient::Channel::ptr_t channel = AmqpClient::Channel::Create("localhost");

 std::string consumer_tag = channel->BasicConsume("kuyruk1");


 while (1)
 {
  AmqpClient::Envelope::ptr_t envelope;
  channel->BasicConsumeMessage(consumer_tag, envelope, 10); // 10 ms timeout

  if (envelope)
  {
   AmqpClient::BasicMessage::ptr_t mes = envelope->Message();


   std::cout << "new mes" << std::endl;

   std::string str = mes->Body();
   std::cout << str << std::endl<<std::endl; 
   
  }
 }

 // done
 return 0;
}


Ekran çıktısı 

Böylece producer.py isimli dosyanın gönderdiği mesajları, C++ uygulamamızdan alıp ekranda görüntülemiş olduk.

Şimdi ise RabbitMQ üretici uygulamasını C++ ile, tüketici uygulamasını ise Python ile yazalım.

C++ producer
#include<iostream>

#include <SimpleAmqpClient/SimpleAmqpClient.h>

int main()
{

 AmqpClient::Channel::ptr_t channel = AmqpClient::Channel::Create("localhost");

 std::string outmes = "message from C++";
 AmqpClient::BasicMessage::ptr_t outgoing_message = AmqpClient::BasicMessage::Create();
 outgoing_message->Body(outmes);

 channel->BasicPublish("", "kuyruk1", outgoing_message);

        return 0;
}

Python consumer
connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
 

channel = connection.channel()
channel.queue_declare(queue='kuyruk1')
 
# sıra üzerinde bir mesaj işlendiğinde kullanılacak 
# geri çağırma fonksiyonu
def callback(ch, method, properties, body):
    print("Bir mesaj geldi => %r" % body)
 
print('Sıraya bir mesaj gelmesi bekleniyor...') 
 
# parametreler vererek kanal üzerindeki işleri işlemeye başlıyoruz
channel.basic_consume(callback,
                      queue='kuyruk1',
                      no_ack=True)

channel.start_consuming()

Ekran çıktısı (C++ uygulamasını 3 defa çalıştırınca)

Bu yazı kapsamında RabbitMQ'nun C++ ve Python ile kullanımına dair örnek uygulamalar gerçekleştirdik. RabbitMQ ile farklı konumlarda çalışan istediğimiz sayıda üretici ve tüketici uygulamaları ekleyerek, farklı diller ile yazılmış uygulamalar arasında asenkron mesaj gönderme/alma işlemlerini kolayca yönetebiliriz.

3 yorum:

  1. Merhaba, hem producer hem de consumer'ı C++ olarak yazdım. İki kodu da çalıştırdığımda ikisi de
    terminate called after throwing an instance of 'AmqpClient::AmqpLibraryException'
    what(): a socket error occurred

    hatası vermektedir. Nedenini nedir acaba, bir bilginiz var mı? Teşekkür ederim.

    YanıtlaSil
    Yanıtlar
    1. Merhaba, RabbitMQ arayüzüne girip "kuyruk1" isminde bir queue oluşturdunuz mu?
      Bu örneklerde fazla detaylara girmedik, Örneğin; kod içerisinde channel->DeclareQueue metodu ile de queue oluşturulabiliyor, ya da exchange oluşturup queue ile bağlantısı yapılabiliyor vs vs.

      Ben bunun yerine arayüz ile gerçekleştirdim queue tanılama işini, onu kontrol edebilirsiniz.

      Sil
    2. Arayüzden queue oluşturduğumda çalıştı, çok teşekkür ederim.

      Sil