许多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
网友评论