使用django+celery+RabbitMQ實現非同步執行

來源:互聯網
上載者:User

RabbitMQ大家應該不陌生,著名的訊息佇列嘛。可惜我最近才聽說它的大名,瞭解之後不禁驚呼,世界上居然還有這種東西! 立刻覺得手裡有了鎚子,就看什麼都是釘子了,主網站不願意乾的操作統統扔給RabbitMQ去做吧 

言歸正傳,先介紹一下這篇文章的應用情境吧。我們知道大型網站的效能非常重要,然而有時不得不做一些相當耗時的操作。 比如SNS網站的“新鮮事兒”系統,我發帖之後,會給所有關注我的人推送一條通知。乍一看沒什麼難的,發帖之後找出關注我的人, 然後產生相應的訊息記錄就行了。但問題是,100個人關注我,就要執行100條INSERT查詢,更要命的是,Web伺服器是同步的, 這100條查詢執行完成之前,使用者是看不到結果的。

怎麼辦呢,這時就輪到訊息佇列上場了。發帖之後只需給隊列發送一條訊息, 告訴隊列“我發文章了”,然後把發帖的結果返回給使用者。 這時另一個叫做worker的進程會取出這條訊息並執行那100條INSERT查詢。這樣,推播通知的操作在後台非同步執行, 使用者就能立即看到發帖結果。更精彩的是,可以運行多個worker實現分布式,多繁重的任務都不在話下了。

好了,來看看今天的主角:

  • django:web架構,其實只能算作配角了;
  • RabbitMQ:訊息佇列系統,負責儲存訊息;
  • celery:worker進程,同時提供在webapp中建立任務的功能。
安裝

安裝環境是MacOS,使用其他動作系統的同學請自行調整安裝命令。

django的安裝配置就不說了,配角嘛。

先來安裝RabbitMQ:

$ sudo port install -n rabbitmq

啟動RabbitMQ:

$ sudo rabbitmq-server -detached

然後安裝celery。到 http://pypi.python.org/pypi/celery#downloads 下載celery並安裝:

$ tar xzvf celery-2.2.7.tar.gz$ cd celery-2.2.7$ python setup.py build$ sudo python setup.py install

這個過程會安裝數個依賴包,包括 pyparsing、kombu、amqplib、anyjson等,如果自動安裝有困難,可以自行下載編譯。

由於要在django中使用,我們還得安裝django-celery這個模組。 到 http://pypi.python.org/pypi/django-celery#downloads 下載 django-celery 並安裝:

$ tar xzvf django-celery-2.2.4.tar.gz$ cd django-celery-2.2.4$ python setup.py build$ sudo python setup.py install

這個過程會安裝依賴包 django-picklefield,如有需要請自行下載編譯。

應用程式樣本

建立測試應用程式:

$ django-admin.py startproject celerytest$ cd celerytest$ django-admin.py startapp hello$ cd hello

然後修改settings.py,在INSTALLED_APPS中加入以下內容:

INSTALLED_APPS = (  ...  'djcelery',          # 加入celery  'hello',             # 測試應用程式}

在settings.py末尾添加RabbitMQ的配置:

import djcelerydjcelery.setup_loader() BROKER_HOST = "localhost"BROKER_PORT = 5672BROKER_USER = "guest"BROKER_PASSWORD = "guest"BROKER_VHOST = "/"

當然,別忘了設定資料庫選項,因為djcelery要用到資料庫的。配置好之後執行:

$ python manage.py syncdb

可以執行 python manage.py 看一下,會發現 djcelery 應用程式給 manage.py 添加了許多celery*開頭的命令, 這些就是控制worker的命令了。

接下來我們寫個task。建立 hello/tasks.py,內容如下:

from celery.decorators import task@taskdef add(x, y):  return x + y

修飾符 @task 將add函數變成了非同步任務。在webapp中調用add並不會立即執行該函數,而是將函數名、 參數等打包成訊息發送到訊息佇列中,再由worker執行實際的代碼(return x + y)。

當然,別忘了必不可少的worker:

$ python manage.py celeryd -l info

在另一個控制台測試一下:

$ python manage.py shell>>> from hello.tasks import add>>> r = add.delay(3,5)     # 執行這一行就能在worker的日誌中看到健全狀態>>> r.wait()8

可以看到,add函數是在worker上啟動並執行,實現了非同步效果。當然,隊列的特性決定了任務並不是即時執行的,可能有延遲, 有時甚至還會丟失,因此,隊列不適合執行關鍵任務。而那些執行結果無關痛癢、對即時性要求不高的任務, 就可以大膽地交給RabbitMQ去處理,將WebApp解放出來吧。

 

轉載自:使用django+celery+RabbitMQ實現非同步執行,作者charlee


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.