使用django+celery+RabbitMQ实现异步执行
RabbitMQ大家应该不陌生,著名的消息队列嘛。可惜我最近才听说它的大名,了解之后不禁惊呼,世界上居然还有这种东西!立刻觉得手里有了锤子,就看什么都是钉子了,主网站不愿意干的操作统统扔给RabbitMQ去做吧
言归正传,先介绍一下这篇文章的应用场景吧。我们知道大型网站的性能非常重要,然而有时不得不做一些相当耗时的操作。比如SNS网站的“新鲜事儿”系统,我发帖之后,会给所有关注我的人推送一条通知。乍一看没什么难的,发帖之后找出关注我的人,然后生成相应的消息记录就行了。但问题是,100个人关注我,就要执行100条INSERT查询,更要命的是,Web服务器是同步的,这100条查询执行完成之前,用户是看不到结果的。
怎么办呢,这时就轮到消息队列上场了。发帖之后只需给队列发送一条消息, 告诉队列“我发帖子了”,然后把发帖的结果返回给用户。这时另一个叫做worker的进程会取出这条消息并执行那100条INSERT查询。这样,推送通知的操作在后台异步执行,用户就能立即看到发帖结果。更精彩的是,可以运行多个worker实现分布式,多繁重的任务都不在话下了。
好了,来看看今天的主角:
安装
安装环境是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 djcelery djcelery.setup_loader() BROKER_HOST = "localhost" BROKER_PORT = 5672 BROKER_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 @task def 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解放出来吧。
建议继续学习:
- 关于IO的同步,异步,阻塞,非阻塞 (阅读:14455)
- Redis消息队列的若干实现方式 (阅读:10685)
- fsockopen 异步处理 (阅读:9015)
- 配合jquery实现异步加载页面元素 (阅读:5367)
- 各消息队列软件产品大比拼 (阅读:5135)
- Django 中 "Data truncated for column xxx" 解决方法 (阅读:4320)
- apache+mod_wsgi+django在windows下的部署 (阅读:4123)
- Django框架ORM操作详解 (阅读:4082)
- 异步编程与响应式框架 (阅读:3890)
- 多核与异步并行 (阅读:3862)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:charlee 来源: idv2
- 标签: celery django RabbitMQ 异步 消息队列
- 发布时间:2011-08-19 23:19:28
- [68] 如何拿下简短的域名
- [68] Go Reflect 性能
- [64] Oracle MTS模式下 进程地址与会话信
- [61] 图书馆的世界纪录
- [60] IOS安全–浅谈关于IOS加固的几种方法
- [60] 【社会化设计】自我(self)部分――欢迎区
- [58] android 开发入门
- [53] 视觉调整-设计师 vs. 逻辑
- [48] 读书笔记-壹百度:百度十年千倍的29条法则
- [47] 界面设计速成