django-celery:任务消息队列

描述

为提高网站性能,很多耗时,但不影响页面正常的操作,可丢给消息队列异步执行

“”“
比如SNS网站的“新鲜事儿”系统,我发帖之后,会给所有关注我的人推送一条通知。乍一看没什么难的,发帖之后找出关注我的人, 然后生成相应的消息记录就行了。但问题是,100个人关注我,就要执行100条INSERT查询,更要命的是,Web服务器是同步的, 这100条查询执行完成之前,用户是看不到结果的。
怎么办呢,这时就轮到消息队列上场了。发帖之后只需给队列发送一条消息, 告诉队列“我发帖子了”,然后把发帖的结果返回给用户。 这时另一个叫做worker的进程会取出这条消息并执行那100条INSERT查询。这样,推送通知的操作在后台异步执行, 用户就能立即看到发帖结果。更精彩的是,可以运行多个worker实现分布式,多繁重的任务都不在话下了
“”“

而在icgoo中是为了jiayou接口的调用,在用户完成订单后,将接口调用的函数放入队列,异步去调用接口,不影响用户页面的返回
django-celery正是所要用到的任务消息队列

相关技术

    RabbitMQ:消息队列系统,负责存储消息;
    celery:worker进程,同时提供在webapp中创建任务的功能。
    django-celery: celery在django的使用

参考文档:

使用django+celery+RabbitMQ实现异步执行

celery官方文档

安装

安装环境是freebsd,用ports安装

Rabbitmq的安装

[liwei@queen ~]$ whereis rabbitmq
rabbitmq: /usr/ports/net/rabbitmq
[liwei@queen ~]$ cd /usr/ports/net/rabbitmq
[liwei@queen /usr/ports/net/rabbitmq]$ sudo make install

celery的安装

[liwei@queen /usr/ports/devel/py-celery]$ sudo make install

django-celery的安装

下载包:http://pypi.python.org/pypi/django-celery#downloads

然后直接运行: sudo python setup.py install

应用程序示例

建立测试应用程序:

$ 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,内容如下:

切换行号显示

   1 from celery.decorators import task
   2
   3 @task
   4 def add(x, y):
   5   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实现异步执行

你可能感兴趣的:(django)