本文根据以下文章讲解Django与Celery如何实现异步队列任务:
http://python.jobbole.com/81953/
https://realpython.com/blog/python/asynchronous-tasks-with-django-and-celery/
之所以要写这篇文章原因:
1. 该文章有一些错误,会导致程序无法运行。
2. 部分步骤说的不是很细,对于第一次接触celery的人来说,会有一点懵逼。
本项目利用python3.5、Django 1.11.2、Celery3.1.18和Redis3.2.1
一、概述
由于大篇幅的文字,为了您的方便,请参阅下表中的每一步的简要信息,并获取相关的代码。
步骤 概要 Git标签
样板 样板下载 V1
建立 集成Celery和Django V2
Celery任务 添加基本的Celery任务 V3
周期性任务 添加周期性任务 V4
本地运行 本地运行我们的应用程序 V5
远程运行 远程运行我们的应用程序 V5
二、什么是Celery
“Celery是一个异步任务队列/基于分布式消息传递的作业队列。它侧重于实时操作,但对调度的支持也很好。”本文,我们将重点讲解周期性执行任务的调度特点。
为什么这一点有用呢?
回想一下你不得不在将来运行某一特定任务的经历。也许你需要每隔一小时访问一个API。或者,也许你需要在这一天结束时发送一批电子邮件。不论任务大小,Celery都可以使得调度周期性任务变的很容易。
你永远不希望终端用户等待那些不必要的页面加载或动作执行完成。如果你的应用程序工作流的一部分是一个需要很长时间的程序,当资源可用时,你就可以使用Celery在后台执行这段程序,从而使你的应用程序可以继续响应客户端的请求。这样可以使任务在应用程序的环境之外运行。
三、构建项目
在深入了解Celery之前,先从Github库中获取开始项目。确保激活一个虚拟的环境,安装必要的软件,并运行迁移。然后启动服务器,通过你的浏览器导航到http://localhost:8000/。你应当能看到‘恭喜你的第一个Django页面’。完成后,关闭服务器。
接下来,我们开始安装celery。
pip install celery==3.1.18
现在,我们通过简单的三步将celery集成到django项目中。
步骤一:创建celery.py
在“picha“目录下,创建celery.py,代码如下:
from __future__ import absolute_import import os from celery import Celery from django.conf import settings # 为Celer程序设置默认的Django设置模块 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'picha.settings') app = Celery('picha') # 在这里使用一个字符串表示工作人员在使用Windows时不必序列化对象。 app.config_from_object('django.conf:settings') app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) @app.task(bind=True) def debug_task(self): print('Request: {0!r}'.format(self.request))
请注意代码中的注释。
步骤二:引入celery应用
为了确保在django启动时加载了celery应用,在settings.py旁边新建__init__.py,并添加以下代码到__init__.py中。
from __future__ import absolute_import # 这将确保在Django启动时始终导入应用程序,以便shared_task将使用此应用程序。 from .celery import app as celery_app
完成以上步骤后,你的项目目录应该是这样的:
├── manage.py ├── picha │ ├── __init__.py │ ├── celery.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py └── requirements.txt
步骤三:安装 Redis作为Celery的“中间件”
Celery使用中间件在django项目与celery监控者之间传递消息。在本教程中,我们使用redis作为消息中间代理。
Redis安装教程和使用教程请参考文章:http://www.chenxm.cc/post/287.html
首先,从官方下载页面或通过brew(BREW安装Redis)安装Redis,然后打开你的终端上,在一个新的终端窗口,启动服务器:
redis-server
你可以通过在终端中输入如下命令测试Redis是否正常工作。
>redis-cli ping PONG
Redis应该回复PONG – 试试吧!
一旦Redis正常启动了,把下面的代码添加到你的settings.py文件中:
# CELERY STUFF BROKER_URL = 'redis://localhost:6379' CELERY_RESULT_BACKEND = 'redis://localhost:6379' CELERY_ACCEPT_CONTENT = ['application/json'] CELERY_TASK_SERIALIZER = 'json' CELERY_RESULT_SERIALIZER = 'json' CELERY_TIMEZONE = 'Africa/Nairobi'
你还需要添加Redis的作为Django项目的依赖:
pip install redis==2.10.3
就是这样了!你现在应该能够在Django中使用Celery。有关设置Celery与Django的更多信息,请查看官方Celery文档。
在继续下面步骤之前,让我们进行一些完整性检查,以确保一切都是正常的。
测试Celery worker已准备好接收任务:
I:\djangoew_picha>celery -A new_picha worker -l info -------------- celery@DESKTOP-PVV9EBS v3.1.18 (Cipater) ---- **** ----- --- * *** * -- Windows-10-10.0.10586-SP0 -- * - **** --- - ** ---------- [config] - ** ---------- .> app: picha:0x20b6c783da0 - ** ---------- .> transport: redis://localhost:6379// - ** ---------- .> results: redis://localhost:6379 - *** --- * --- .> concurrency: 8 (prefork) -- ******* ---- --- ***** ----- [queues] -------------- .> celery exchange=celery(direct) key=celery [tasks] . new_picha.celery.debug_task [2017-08-29 09:32:32,406: INFO/MainProcess] Connected to redis://localhost:6379// [2017-08-29 09:32:33,425: INFO/MainProcess] mingle: searching for neighbors [2017-08-29 09:32:36,433: INFO/MainProcess] mingle: all alone [2017-08-29 09:32:41,453: WARNING/MainProcess] d:\software\python35\lib\site-packages\celery\fixups\django.py:265: UserWarning: Using settings.DEBUG leads to a memory leak, never use this setting in production environments! warnings.warn('Using settings.DEBUG leads to a memory leak, never ' [2017-08-29 09:32:41,455: WARNING/MainProcess] celery@DESKTOP-PVV9EBS ready.
使用CTRL-C杀死该段程序。现在,测试Celery任务调度程序是否已经准备好:
I:\djangoew_picha>celery -A new_picha beat -l info celery beat v3.1.18 (Cipater) is starting. __ - ... __ - _ Configuration -> . broker -> redis://localhost:6379// . loader -> celery.loaders.app.AppLoader . scheduler -> celery.beat.PersistentScheduler . db -> celerybeat-schedule . logfile -> [stderr]@%INFO . maxinterval -> now (0s) [2017-08-29 09:33:48,048: INFO/MainProcess] beat: Starting...
在上述完成时再次终止该进程。
celery命令总结:
$ celery -A picha worker -l info #Celery worker接收任务启动 $ celery -A picha beat -l info #Celery 任务调度程序启动
使用注意:
必须要在项目文件夹下的cmd中输入该命令,否则会提示ImportError: No module named 'new_picha'错误