-
当Django执行中遇到耗时操作,比如请求第三方发送短信,为了不阻塞进程,应当将耗时代码从主业务中解耦出来(使用生产者消费者模式)
在Django中可使用Celery完成异步,我们在使用生产者消费者模式时,只需要关注任务本身,极大的简化了程序员的开发流程。
可使用RabbitMQ或者Redis作为消息队列的容器
Celery是什么
介绍:
- 一个简单、灵活且可靠、处理大量消息的分布式系统,可以在一台或者多台机器上运行。
- 单个 Celery 进程每分钟可处理数以百万计的任务。
- 通过消息进行通信,使用消息队列(broker)在客户端和消费者之间进行协调。
安装方式 pip install -U Celery
使用Celery定义发送短信任务
- 在项目根目录,即manage.py同级目录下创建Celery的包,如命名为celery_tasks
- 在celery_tasks包内创建main.py文件,创建Celery实例。
# celery启动文件
from celery import Celery
# 创建celery实例
celery_app = Celery('meiduo')
- 加载Celery配置,在celery_tasks包内创建config.py文件,指定消息队列位置,我这里使用的是Redis, 最好还是用RabbitMQ
# 指定消息队列的位置
# 这里使用redis作为队列容器
broker_url = "redis://127.0.0.1:6379/12"
- 定义发送短信任务:在celery_tasks包内创建任务包sms,包内创建任务文件tasks.py
特别注意:tasks.py命文件名必须为此名,不可自定义其他命名!!
# bind:保证task对象会作为第一个参数自动传入
# name:异步任务别名
# retry_backoff:异常自动重试的时间间隔 第n次(retry_backoff×2^(n-1))s
# max_retries:异常自动重试次数的上限
from meiduo_mall.libs.yuntongxun.sms import CCP
# constants为自定义的过期时间配置文件
from celery_tasks.sms import constants
from celery_tasks.main import app
# 使用装饰器装饰任务
@app.task(bind=True, name="send_sms", retry_backoff=3)
def send_sms(self,mobile,sms_code):
"""
异步发送短信任务
:param self:
:param mobile:手机号
:param sms_code: 短信验证码
:return: 成功0,失败-1
"""
# 将耗时的代码封装在一个方法中
ccp = CCP()
ret = ccp.send_template_sms(mobile, [sms_code,constants.SMS_CODE_EXPIRES],1)
if ret != 0:
raise self.retry(exe=Exception("发送短信失败"), max_retries=3)
return ret
- 在main.py文件中注册任务
# celery启动文件
from celery import Celery
# 创建celery实例
celery_app = Celery('meiduo')
# 加载celery配置
celery_app.config_from_object('celery_tasks.config')
# 自动注册celery任务
celery_app.autodiscover_tasks(['celery_tasks.sms'])
Celery任务就定义完成了,只需要在指定位置调用任务即可:
Celery任务开启和调用
-
启动Celery服务:
在项目根目录下执行
celery -A celery_tasks.main worker -l info
- -A指对应的应用程序, 其参数是项目中 Celery实例的位置。
- worker指这里要启动的worker。
- -l指日志等级,比如info等级。
- 调用发送短信任务
在指定位置,执行Celery任务,参照上篇文章:
Django-实现图形验证码、短信验证码功能(二)
ccp_send_sms_code.delay(mobile, sms_code)
该任务将会异步执行,不会阻塞后续代码执行。