Celery简介
celery是一个功能完备即插即用的异步任务队列系统。它适用于异步处理问题,当发送邮件,或者文件上传,图像处理等一些比较耗时的操作,我们可以将其异步执行,这样用户不需要等待太久,提高用户体验。
参考文档
Celery的特点是:
- 简单,易于使用和维护,有丰富的文档。
- 高效,单个celery进程每分钟可以处理百万个任务。
- 灵活,celery几乎每个部分都可以自定义扩展。
任务队列是一种跨线程、跨机器工作的一种机制。
任务队列中包含称作任务的工作单元。有专门的工作进程持续不断的监视任务队列,并从中获得新的任务并处理。
celery通过消息进行通信,通常使用一个叫做Broker(中间人)来调client(任务的发出者)和worker(任务的处理者)。clients发出消息到队列中,broker将队列中的信息派发给worker来处理。
Celery架构
Celery的架构三部分组成,消息队列(message broker)、任务执行单元(worker)、任务执行结果存储(task result store) 组成。
Celery本身不提供消息队列功能,但是可以很方便地和第三方提供的消息中间件进行集成,包括RabbitMQ,Redis,MongoDB等。
Celery安装
pip install -U celery
Celery使用
使用Celery第一件要做的最为重要的就是需要先创建一个Celery实例,我们一般叫做Celery应用,或者更简单直接叫做一个app。app应用是我们使用Celery所有功能的入口,比如创建任务,管理任务等,在使用Celery的时候,app必须能够被其他的模块导入。
在项目中使用Celery时,一般将celery任务目录直接放在项目的根目录下即可,路径:
ttzxapi/
├── mycelery/
├── config.py # 配置文件
├── __init__.py
├── main.py # 主程序
└── sms/ # 一个目录可以放置多个任务,该目录下存放当前任务执行时需要的模块或依赖
└── tasks.py # 任务的文件,名称必须是这个!!!
main.py, 代码:
# 主程序
from celery import Celery
# 创建celery实例对象
app = Celery("ttzx")
# 通过app对象来加载配置
app.config_from_object("mycelery.config")
# 自动搜索并加载任务
# 参数必须是一个列表,里面的每一个任务都是任务的路径名称
# app.autodiscover_tasks(["任务1", "任务2"])
app.autodiscover_tasks(["mycelery.sms", "mycelery.mail"])
# 启动celery的命令
# 强烈建议切换目录到项目的根目录下启动celery!!
# celery -A mycelerymain worker --loglevel=info
配置文件 config.py ,代码:
# 任务队列的链接地址
broker_url = 'redis://127.0.0.1:6379/15'
# 结果队列的链接地址
result_backend = 'redis://127.0.0.1:6379/14'
创建一个任务文件 sms/tasks.py,并创建任务,代码:
# celery的任务必须写在tasks.py的文件中,别的文件名称不识别!!!!
from celery.main import app
@app.task #name表示设置任务的名称,如果不填写,则默认使用函数名作为任务名
def send_sms():
print("发送短信!!!")
@app.task #name表示设置任务的名称,如果不填写,则默认使用函数名作为任务名
def send_mail():
print(“发送邮件!!!”)
启动运行celery。。
其他参考
把django和celery进行组合
在main.py主程序中对django的配置文件进行加载
# 主程序
import os
from celery import Celery
# 创建celery实例对象
app = Celery("ttzx")
# 把celery和django进行组合,识别和加载django的配置文件
os.environ.setdefault('DJANGO_SETTINGS_MODULE','ttzxapi.settings.dev')
# 对django框架进行初始化
import django
django.setup()
# 通过app对象加载配置
app.config_from_object("mycelery.config")
# 加载任务
# 参数必须是一个列表,里面的每一个任务都是任务的路径名称
# app.autodiscover_tasks(["任务1","任务2"])
app.autodiscover_tasks(["mycelery.sms"])
# 启动Celery的命令
# 强烈建议切换到mycelery跟目录下启动
# celery -A main worker --loglevel=info
在需要使用django配置的任务中,直接加载配置,所以我们把注册的短信发送功能,整合成一个任务函数,代码:
from mycelery.main import app
from .yuntongxun.sms import CCP
from ttzxapi.settings import constants
import logging
from django.conf import settings
log = logging.getlogger("django")
@app.task(name="send_sms")
def send_sms(mobile, sms_code):
"""异步发送短信"""
ccp = CCP()
try:
result = ccp.send_template_sms(mobile, [sms_code, constans.SMS_CODE_EXPIRE//60], settings.SMS.get("_templateID"))
return result
except:
log.error("发送短信验证码失败!手机号: %s" % mobile)
在这个任务中,我们需要加载短信发送的sdk和相关的配置常量,所以我们可以直接把django中的短信发送模块和相关的常量配置文件直接剪切到当前sms任务目录中
mycelery/
├── config.py
├── __init__.py
├── main.py
└── sms/
├── constant.py
├── __init__.py
├── tasks.py
└── yuntongxun
├── CCPRestSDK.py
├── __init__.py
├── sms.py
└── xmltojson.py
再次启动项目即可。
最终在django里面,我们调用Celery来异步执行任务。需要完成2个步骤:
# 1. 声明一个和celery一模一样的任务函数,但是我们可以导包来解决
from mycelery.sms.tasks import send_sms
# 2. 调用任务函数,发布任务
send_sms.delay(mobile,sms_code)
# send_sms.delay() 如果调用的任务函数没有参数,则不需要填写任何内容