许多Django应用需要执行异步任务, 以便不耽误http request的执行. 我们也可以选择许多方法来完成异步任务, 使用Celery是一个比较好的选择, 因为Celery有着大量的社区支持, 能够完美的扩展, 和Django结合的也很好. Celery不仅能在Django中使用, 还能在其他地方被大量的使用. 因此一旦学会使用Celery, 我们可以很方便的在其他项目中使用它.
问题分析:
- 在网络请求出现问题时,是一个耗时操作。在同一个主线程中,耗时请求就要等待主线程执行完毕之后,在去加载请求操作。
解决问题:
- 使用线程,异步执行 耗时操作(原生的threading线程会出现GIL全局解释器锁的问题)
弊端解决:
- 使用celery,解决GIL全局解释器锁的问题
Celery介绍
Celery的主要用处是执行异步任务, 可以选择延期或定时执行功能. 为什么需要执行异步任务呢?
假设用户正发起一个request, 并等待request完成后返回. 在这一request后面的view功能中, 我们可能需要执行一段花费很长时间的程序任务, 这一时间可能远远大于用户能忍受的范围. 当这一任务并不需要立刻执行时, 我们便可以使用Celery在后台执行, 而不影响用户浏览网页. 当有任务需要访问远程服务器完成时, 我们往往都无法确定需要花费的时间.
定期执行某些任务. 比如每小时需要检查一下天气预报, 然后将数据储存到数据库中. 我们可以编写这一任务, 然后让Celery每小时执行一次. 这样我们的web应用便能获取最新的天气预报信息.
我们这里所讲的任务task, 就是一个Python功能(function). 定期执行一个任务可以被认为是延时执行该功能. 我们可以使用Celery延迟5分钟调用function task1, 并传入参数(1, 2, 3). 或者我们也可以每天午夜运行该function.
1. 我们偏向于将Celery放入项目中, 便于task访问统一数据库和Django设置.
2. 当task准备运行时, Celery会将其放入列队queue中. queue中储存着可以运行的task的list. 我们可以使用多个queue, 但为了简单, 这里我们只使用一个.
3. 将任务task放入queue就像加入todo list一样. 为了使task运行, 我们还需要在其他线程中运行的苦工worker. worker实时观察着代运行的task, 并逐一运行这些task. 你可以使用多个worker, 通常他们位于不同服务器上. 同样为了简单起见, 我们这只是用一个worker.
Celery执行流程图:

执行流程:
- 在项目文件下创建celery_tasks应用用于保存celery异步任务
- 创建一个celery的启动文件,相当与Django manage文件--> 相对与流程图worker
- 创建一个config文件,用于连接redis,任务队列中--> 相对与流程图broker
- 创建一个sms目录,celery_tasks/sms/目录下创建tasks.py文件,用于保存发送短信的异步任务-->任务的发布文件
- 在视图中使用delay方法调用任务,执行异步线程方法--> 相对与流程图任务发布方法中心
安装Celery
使用pip在vietualenv中安装:
pip install django-celery
创建Celery应用:
-
目录结构
image.png
一. 在celery_tasks目录下创建config.py文件,用于保存celery的配置信息
# 配置连接的redis, 任务broker
broker_url = "redis://127.0.0.1/14"
二. 在celery_tasks目录下创建main.py文件,用于作为celery的启动文件
from celery import Celery
# 为celery使用django配置文件进行设置
import os
if not os.getenv('DJANGO_SETTINGS_MODULE'):
#'project.settings.dev':项目的配置文件,添加Celery配置
os.environ['DJANGO_SETTINGS_MODULE'] = 'project.settings.dev'
# 创建celery应用
app = Celery('jianshu')
# 导入celery配置
app.config_from_object('celery_tasks.config')
# 自动注册celery任务(自动查询sms文件下的方法)
app.autodiscover_tasks(['celery_tasks.sms'])
三.在celery_tasks目录下创建sms目录,用于放置的异步任务相关代码
# 存放异步任务的发布队列方法
import logging
import time
from celery_tasks.main import app
# 调用配置文件中日志器
logger = logging.getLogger("django")
#app装饰器能够在视图中调用该异步任务
@app.task(name='send_sms_code')
def send_sms_code():
# 发送短信验证码
try:
'''此处异步任务方法'''
....
time.sleep(10)
except Exception as e:
logger.error("发送验证码短信[异常])
三. 在项目views.py中改写主线程中的任务,使用celery异步任务
from celery_tasks.sms.tasks import send_sms_code
.....
send_sms_code.delay()
四.启动Celery应用
# 终端启动命令(在vietualenv中cd到celery_tasks目录下,)
celery -A celery_tasks.main worker -l info
