RabbitMQ ile Python Uygulamaları – 1

Merhaba

Özellikle web uygulamalarında request ile response arasında ki süre kısa olmalıdır. Aksi takdirde kullanıcılar web sayfasının karşılarına gelmeleri için uzun bir süre bekleyeceklerdir. Bu probleme neden olan başlıca etmenler ise kullanıcıları ilgilendirmeyen işlemlerdir. Bu duruma en güzel örnek aşağıda ki yazılımsal ihtiyaçtır.

Web sitesine üye olan kullanıcı ile aynı ilde bulunan diğer mevcut kullanıcıların tamamına mail gönderilmesi.

Eğer bu mailler üye işlemi sırasında gerçekleştirilmek istenirse, üye formunu dolduran kullanıcı uzun bir süre sayfanın gelmesini bekleyecektir. Çünkü backend uygulama üye işlemi tamamlandıktan sonra N sayıda kullanıcıya mail göndermeye çalışacaktır.

Beni RabbitMQ ile tanıştıran neden ise web uygulaması üzerinden network taraması gerçekleştirme ve sonuçları veri tabanına kayıt etme ihtiyacıdır.

RabbitMQ Nedir ?

RabbitMQ bir “message broker” yazılımıdır. Temel olarak bir uygulamadan mesaj alıp, başka bir uygulamaya iletme işlemini gerçekleştirmektedir. RabbitMQ sistemini en güzel betimleyen örnek ise Posta Ofisi örneğidir. A kişisi, B kişisine zarf göndermek istediğinde posta ofisine gelir zarfı bırakır. Posta Ofisindeki görevli ise bu zarfı sahibine iletir.

Producer , Queue ve Consumer

RabbitMQ ile çalışıldığında bilinmesi gereken 3 adet terim bulunmaktadır. Bunları tek tek açıklayalım

Producer : RabbitMQ sistemine mesaj üreten yazılım. Posta Ofisi metaforuna göre, zarf göndermek isteyen kullanıcıdır.

Queue : Kuyruk anlamına gelir ve RabbitMQ üzerinde depolanan mesajları ifade eder. Bu mesajlar üreticiler(producer) tarafından RabbitMQ’ya gönderilmektedir ve consumer’lara iletilecektir. Birden fazla producer tarafından aynı “kuyruğa” mesaj gönderilebilir.

Consumer : Kuyruğa gönderilen mesajları alan uygulamalardır. Bu uygulamalar RabbitMQ’nun kuyruğa gelen mesajı iletmelerini beklemektedir.

RabbitMQ ve Kütüphanelerin Kurulumu

RabbitMQ serverının kurulumu oldukça kolaydır. Ubuntu için aşağıdaki komut yeterli olacaktır. Centos gibi farklı dağıtımlar içinse http://www.rabbitmq.com/download.html adresindeki adımlar uygulanabilir.

sudo apt-get install rabbitmq-server
sudo /etc/init.d/rabbitmq-server start

RabbitMQ sistemini kullanacak publisher ve consumer uygulamaları ise python ile geliştireceğiz. Bu nedenle rabbitmq için geliştirilmiş pika isimli kütüphane kurulmalıdır.

pip install pika==0.9.8

İlk Uygulama

İlk uygulamada Kuyruk’a mesaj gönderen publisher.py ve kuyruktan mesaj alan consumer.py isminde 2 adet python dosyası yazılacaktır.

Publisher.py dosyasının kodları

#!/usr/bin/env python
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(
        host='localhost'))
channel = connection.channel()

channel.queue_declare(queue='hello')

channel.basic_publish(exchange='',
                      routing_key='hello',
                      body='Hello World!')
print " [x] Sent 'Hello World!'"
connection.close()

İlk satırda pika isimli modül import edilmiştir. Ardından localhost‘ta ki RabbitMQ sunucusuna bağlanılmıştır. RabbitMQ’yu farklı bir sunucuda çalıştıranlar, localhost yerine sunucunun ip adresi yazmalıdırlar.

RabbitMQ mesajları kuyrukta tutmaktadır. Eğer producer var olmayan bir kuyruk’a mesaj gönderirse, RabbitMQ bu mesajı çöpe atacaktır. Bu nedenle queue_declare metodu ile hello isminde bir kuyruk tanımlanmaktadır.

Publisher mesajları hiçbir zaman direk olarak kuyruk’a göndermemektedir. Mesajları alıp kuyruğa işleyen exchange adında bir yapı mevcuttur. Bu nedenle mesaj oluşturulurken exchange belirtilmelidir. Boş bırakıldığında default exchange mesajı karşılayacaktır. Mesajın body kısmına  “Hello World!”  yazılarak mesaj iletilmiştir.

Son adımda ise bağlantı sonlandırılmıştır.

Consumer.py dosyasının kodları

#!/usr/bin/env python
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters(
        host='localhost'))
channel = connection.channel()

channel.queue_declare(queue='hello')

print ' [*] Waiting for messages. To exit press CTRL+C'

def callback(ch, method, properties, body):
    print " [x] Received %r" % (body,)

channel.basic_consume(callback,
                      queue='hello',
                      no_ack=True)

channel.start_consuming()

Kuyruktaki messajı alıp ekrana yazacak olan consumer.py ise öncelikle hangi kuyruktan mesaj okuyacağını bilmelidir. Bunun için queue_declare metodu kullanarak kuyruk tanımlanmıştır.

Kuyruktan mesaj geldiğinde  callback fonksiyonunu çağırılacaktır. Alınan mesajın body kısmını ekrana yazan callback fonksiyonu tanımlanmıştır.

Ardından basic_consume ile mesaj kuyruktan okunarak işleme alınır.

Consumer.py çalıştığında process olarak beklemede kalıp mesajın gelmesini bekleyecektir. Kuyruktan gelen her mesaj için callback fonksiyonunu çağırarak yeni mesajlar için hazır vaziyette beklemede kalacaktır.

Sonuç

Publisher.py ile mesaj kuyruğa mesaj gönderilmiştir.

mince@rootlab python (master) $ python publisher.py 
 [x] Sent 'Hello World!'
mince@rootlab python (master) $

Consumer.py henüz çalışmamaktadır. Çalıştığı  anda kuyrukta ki mesaj kendisine RabbitMQ tarafından gönderilecektir.

mince@rootlab python (master) $ python consumer.py 
 [*] Waiting for messages. To exit press CTRL+C
 [x] Received 'Hello World!'
# Process beklemede

RabbitMQ’dan gelen mesaj alınarak ekrana yazılmıştır.

Yazının ikinci bölümü için: https://www.mehmetince.net/rabbitmq-ile-python-uygulamalari-2/

Referans : Bu yazı serisinin hazırlanmasında kullanılan en önemli kaynak rabbitmq dökümantasyonudur. Bu dökümantasyona aşağıdaki linkten ulaşabilirsiniz.

http://www.rabbitmq.com/getstarted.html