异步任务队列Celery在Django中的使用方法


Posted in Python onJune 07, 2018

前段时间在Django Web平台开发中,碰到一些请求执行的任务时间较长(几分钟),为了加快用户的响应时间,因此决定采用异步任务的方式在后台执行这些任务。在同事的指引下接触了Celery这个异步任务队列框架,鉴于网上关于Celery和Django结合的文档较少,大部分也只是粗粗介绍了大概的流程,在实践过程中还是遇到了不少坑,希望记录下来帮助有需要的朋友。

一、Django中的异步请求

Django Web中从一个http请求发起,到获得响应返回html页面的流程大致如下:http请求发起 -- http handling(request解析) -- url mapping(url正则匹配找到对应的View) -- 在View中进行逻辑的处理、数据计算(包括调用Model类进行数据库的增删改查)--将数据推送到template,返回对应的template/response。

异步任务队列Celery在Django中的使用方法

图1. Django架构总览

同步请求:所有逻辑处理、数据计算任务在View中处理完毕后返回response。在View处理任务时用户处于等待状态,直到页面返回结果。

异步请求:View中先返回response,再在后台处理任务。用户无需等待,可以继续浏览网站。当任务处理完成时,我们可以再告知用户。

二、关于Celery

Celery是基于Python开发的一个分布式任务队列框架,支持使用任务队列的方式在分布的机器/进程/线程上执行任务调度。

异步任务队列Celery在Django中的使用方法

图2. Celery架构

图2展示的是Celery的架构,它采用典型的生产生-消费者模式,主要由三部分组成:broker(消息队列)、workers(消费者:处理任务)、backend(存储结果)。实际应用中,用户从Web前端发起一个请求,我们只需要将请求所要处理的任务丢入任务队列broker中,由空闲的worker去处理任务即可,处理的结果会暂存在后台数据库backend中。我们可以在一台机器或多台机器上同时起多个worker进程来实现分布式地并行处理任务。

三、Django中Celery的实现

在实际使用过程中,发现在Celery在Django里的实现与其在一般.py文件中的实现还是有很大差别,Django有其特定的使用Celery的方式。这里着重介绍Celery在Django中的实现方法,简单介绍与其在一般.py文件中实现方式的差别。

1. 建立消息队列

首先,我们必须拥有一个broker消息队列用于发送和接收消息。Celery官网给出了多个broker的备选方案:RabbitMQ、Redis、Database(不推荐)以及其他的消息中间件。在官网的强力推荐下,我们就使用RabbitMQ作为我们的消息中间人。在Linux上安装的方式如下:

sudo apt-get install rabbitmq-server

命令执行成功后,rabbitmq-server就已经安装好并运行在后台了。

另外也可以通过命令rabbitmq-server来启动rabbitmq server以及命令rabbitmqctl stop来停止server。

更多的命令可以参考rabbitmq官网的用户手册:https://www.rabbitmq.com/manpages.html

2. 安装django-celery

pip install celery
pip install django-celery

3. 配置settings.py

首先,在Django工程的settings.py文件中加入如下配置代码:

import djcelery
djcelery.setup_loader()
BROKER_URL= 'amqp://guest@localhost//'
CELERY_RESULT_BACKEND = 'amqp://guest@localhost//'

其中,当djcelery.setup_loader()运行时,Celery便会去查看INSTALLD_APPS下包含的所有app目录中的tasks.py文件,找到标记为task的方法,将它们注册为celery task。BROKER_URL和CELERY_RESULT_BACKEND分别指代你的Broker的代理地址以及Backend(result store)数据存储地址。在Django中如果没有设置backend,会使用其默认的后台数据库用来存储数据。注意,此处backend的设置是通过关键字CELERY_RESULT_BACKEND来配置,与一般的.py文件中实现celery的backend设置方式有所不同。一般的.py中是直接通过设置backend关键字来配置,如下所示:

app = Celery('tasks', backend='amqp://guest@localhost//', broker='amqp://guest@localhost//')

然后,在INSTALLED_APPS中加入djcelery:

INSTALLED_APPS = (
  ……  
  'qv',
  'djcelery'
  ……  
)

4. 在要使用该任务队列的app根目录下(比如qv),建立tasks.py,比如:

异步任务队列Celery在Django中的使用方法

在tasks.py中我们就可以编码实现我们需要执行的任务逻辑,在开始处import task,然后在要执行的任务方法开头用上装饰器@task。需要注意的是,与一般的.py中实现celery不同,tasks.py必须建在各app的根目录下,且不能随意命名。

5. 生产任务

在需要执行该任务的View中,通过build_job.delay的方式来创建任务,并送入消息队列。比如:

异步任务队列Celery在Django中的使用方法

6. 启动worker的命令

#先启动服务器
python manage.py runserver
#再启动worker 
python manage.py celery worker -c 4 --loglevel=info

四、补充

Django下要查看其他celery的命令,包括参数配置、启动多worker进程的方式都可以通过python manage.py celery --help来查看:

异步任务队列Celery在Django中的使用方法

另外,Celery提供了一个工具flower,将各个任务的执行情况、各个worker的健康状态进行监控并以可视化的方式展现,如下图所示:

异步任务队列Celery在Django中的使用方法

Django下实现的方式如下: 

1. 安装flower:

pip install flower

2. 启动flower(默认会启动一个webserver,端口为5555):

python manage.py celery flower

3. 进入http://localhost:5555即可查看。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python+微信接口实现运维报警
Aug 27 Python
Python实现简易版的Web服务器(推荐)
Jan 29 Python
python smtplib模块自动收发邮件功能(二)
May 22 Python
Pycharm代码无法复制,无法选中删除,无法编辑的解决方法
Oct 22 Python
在python中实现调用可执行文件.exe的3种方法
Jul 07 Python
pandas中DataFrame修改index、columns名的方法示例
Aug 02 Python
python识别文字(基于tesseract)代码实例
Aug 24 Python
pyqt5、qtdesigner安装和环境设置教程
Sep 25 Python
Python中求对数方法总结
Mar 10 Python
Pycharm2020.1安装无法启动问题即设置中文插件的方法
Aug 07 Python
Python实现日志实时监测的示例详解
Apr 06 Python
Python OpenCV实现图像模板匹配详解
Apr 07 Python
浅谈python中对于json写入txt文件的编码问题
Jun 07 #Python
Python查看微信撤回消息代码
Jun 07 #Python
spark: RDD与DataFrame之间的相互转换方法
Jun 07 #Python
Python简单实现网页内容抓取功能示例
Jun 07 #Python
pyspark 读取csv文件创建DataFrame的两种方法
Jun 07 #Python
redis之django-redis的简单缓存使用
Jun 07 #Python
PHP实现发送和接收JSON请求
Jun 07 #Python
You might like
laravel框架中表单请求类型和CSRF防护实例分析
2019/11/23 PHP
jquery $.ajax入门应用一
2008/11/19 Javascript
基于jquery的button默认enter事件(回车事件)。
2011/05/18 Javascript
浏览器解析js生成的html出现样式问题的解决方法
2012/04/16 Javascript
一些常用弹出窗口/拖放/异步文件上传等实用代码
2013/01/06 Javascript
js中eval()函数和trim()去掉字符串左右空格应用
2013/02/02 Javascript
window.navigate 与 window.location.href 的使用区别介绍
2013/09/21 Javascript
Jquery操作js数组及对象示例代码
2014/05/11 Javascript
IE浏览器IFrame对象内存不释放问题解决方法
2014/08/22 Javascript
微信小程序 五星评分(包括半颗星评分)实例代码
2016/12/14 Javascript
微信小程序 配置文件详细介绍
2016/12/14 Javascript
JavaScript中创建对象的7种模式详解
2017/02/21 Javascript
vue2 mint-ui loadmore实现下拉刷新,上拉更多功能
2018/03/21 Javascript
mpvue 单文件页面配置详解
2018/12/02 Javascript
深入分析element ScrollBar滚动组件源码
2019/01/22 Javascript
使用zrender.js绘制体温单效果
2019/10/31 Javascript
微信公众号网页分享功能开发的示例代码
2020/05/27 Javascript
javascript实现支付宝滑块验证码效果
2020/07/24 Javascript
[55:45]DOTA2上海特级锦标赛D组败者赛 Liquid VS COL第一局
2016/02/28 DOTA
[01:20]2018DOTA2亚洲邀请赛总决赛战队Mineski晋级之路
2018/04/07 DOTA
[51:36]EG vs VP 2018国际邀请赛淘汰赛BO3 第一场 8.24
2018/08/25 DOTA
python网络爬虫采集联想词示例
2014/02/11 Python
python+Django+apache的配置方法详解
2016/06/01 Python
Python读取一个目录下所有目录和文件的方法
2016/07/15 Python
Python实现将数据框数据写入mongodb及mysql数据库的方法
2018/04/02 Python
python调用外部程序的实操步骤
2019/03/04 Python
从0开始的Python学习016异常
2019/04/08 Python
Python中一个for循环循环多个变量的示例
2019/07/16 Python
pytorch实现从本地加载 .pth 格式模型
2020/02/14 Python
html5中JavaScript removeChild 删除所有节点
2014/05/16 HTML / CSS
数组越界问题
2015/10/21 面试题
介绍一下Linux中的链接
2016/05/28 面试题
材料员岗位职责
2014/03/13 职场文书
《东方明珠》教学反思
2014/04/20 职场文书
2014年便民服务中心工作总结
2014/12/20 职场文书
升学宴家长致辞
2015/07/27 职场文书