fatiherikli

Konuya girmeden önce; artık blog post'larım django.org.tr gezegeninde yayınlanmakta. Bu yüzden bana tumblr'ın getirtiği baştan salma yazı yazma alışkanlığımı sonlandırmak istiyorum. Başlıksız ya da içeriksiz post atmak her ne kadar güzel olsa da post'lar sadece tumblr üzerinden okunmuyor. Artık özen göstererek yazmak gerekecek :)

Distributed Computing

RabbitMQ,  zaten dağıtık hesaplama (distributed computing) konusunda ünlü olan Erlang dili ile geliştirilmiş AMQP(Advanced Message Queuing Protocol) protokolü üzerinde çalışan open-source bir message broker (mesaj kuyruğu diyebiliriz) yazılımıdır. Bu ve bunun gibi message broker yazılımları sayesinde kullandığımız dilden bağımsız bir şekilde yapılması uzun süren işlemleri (hesaplamalar, email vb.) çeşitli makinalara ya da aynı makina üzerindeki birden fazla worker'a dağıtabiliriz.

Gerçek hayattan bir örnek verecek olursak; scale edilmesi gereken bir django uygulamasında request ve response arasında uzun süren işlemler ya da web ile alakası olmayan ayrı bir katmanda yapılan bir iş olmaması gerekmektedir. Misal kullanıcılara bir ya da birden fazla email göndermek, uzun süren hesaplamalar yapmak, kullanıcıya yeni bir demo site açmak gibi …

Requirements;

Paket manager'ımız ile rabbitmq-server'ı yükleyelim.

apt-get install rabbitmq-server

Kurulum bittiğinde server otomatik olarak başlatılacaktır. Şimdi de python kütüphanemizi yükleyelim.

pip install pika

Bu işlem de bittikten sonra yükleyeceğimiz başka bir şey kalmıyor. Örneklere geçebiliriz.

Bir mesaj kuyruğu uygulamasında üç temel yapı vardır; Consumer, Queue ve Publisher.

Consumer

Publisher'dan gelecek olan mesajlar için sürekli dinlemede olan bir nevi sunucudur. Aynı anda birden fazla consumer çalıştırabilirsiniz. RabbitMQ tüm consumer'lara eşit miktarda iş yükü dağıtmaya çalışacaktır.

Queue

Task yani görevlerin saklandığı kuyruktur. Eğer tek consumer var ise bu yapı FIFO (First in First out) yani -ilk giren ilk çıkar- şeklindedir. Zira birden fazla consumer olduğunda RabbitMQ işleri dağıtmaktadır.

Publisher

Consumer'a işleri gönderen uygulamadır. Bu bir django application'ı olabilir.

Şimdi örneğimize geçelim; peş peşe email gönderen bir uygulama simüle edelim. İlk olarak receiver yani consumer uygulamamızı yazalım.

consumer.py içeriği;

import pika, time

def callback(ch, method, properties, body):
    print "email gonderiliyor; ", body
    time.sleep(1) # gercekci olsun diye 1 saniye bekletiyoruz :)
    print "email gonderildi."

def main():
    connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
    channel = connection.channel()
    channel.queue_declare(queue='mailing')
    channel.basic_consume(callback, queue='mailing', no_ack=True)
    channel.start_consuming()

if __name__ == "__main__":
    main()

Örnekte mailing adında bir kuyruk oluşturduk ve o kuyruk üzerinde consuming işlemini başlattık. Örneği çalıştırdığınızda program dinlemeye geçecektir. Bir mesaj geldiğinde ise oluşturduğumuz callback fonksiyonu mesaj parametresi ile birlikte işlemeye başlayacaktır. Consumer uygulamamızı aşağıdaki gibi başlatalım;

python consumer.py

Şimdi ise publisher'ımızı yazalım.

publisher.py içeriği;

import sys
import pika

def main():
    connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
    channel = connection.channel()
    channel.queue_declare(queue='mailing')
    channel.basic_publish(exchange='', routing_key='mailing',body=sys.argv[1])
    connection.close()

if __name__ == "__main__":
    main()

Consumer uygulamamızdaki gibi aynı kuyruğa bağlandık ve bu sefer kuyruğa mesaj göndermesini istedik. Publisher uygulamamızı aşağıdaki gibi çalıştırdığımızda dinlemede olan consumer'ımız üzerine görevi yapacaktır.

python publisher.py fatiherikli@gmail.com

Burada önemli olan kısım publisher'dan ziyade consumer uygulamamızın yapılandırmasıdır. Örnekte biz tek bir consumer uygulaması çalıştırdık. Peş peşe publisher.py üzerinden komut göndermeye çalıştığınızda Consumer'ınız sırasıyla gönderdiğiniz komutları çalıştıracaktır.

Şimdi ise consumer.py 'nizi farklı terminallerde aynı anda çalıştırın. Örnek olarak 3 tane consumer'ınız dinlemede olsun. Publisher'ınız üzerinden peş peşe mesaj göndermeye çalıştığınızda her consumer'da aynı görev sayısı olacak şekilde işlemlerin dağıtıldığını göreceksiniz.

Ayrıca Django ve RabbitMQ etkileşimini daha da kolaylaştıran celery projesini incelemenizi tavsiye ederim;

[http://celeryproject.org/](http://celeryproject.org/)

comments powered by Disqus