前言:
随着互联网的飞速发展,随之而来的我们以往的配置已经无法满足用户的需求,我们需要寻求更高效更便捷的方法来应对不同的需求,其中有同步到异步的过度就是一个很好的例子,接下来我们将利用异步实现短信/邮箱的异步发送
1.同步
多任务, 多个任务之间执行的时候要求有先后顺序,必须一个先执行完成之后,另一个才能继续执行, 只有一个主线
2.异步
多任务, 多个任务之间执行没有先后顺序,可以同时运行,执行的先后顺序不会有什么影响,存在的多条运行主线
3. 阻塞
从调用者的角度出发,如果在调用的时候,被卡住,不能再继续向下运行,需要等待,就说是阻塞
3.同步和异步的区别
同步在遇到一些外界未知因素时会发生阻塞,程序会暂停执行,即使后续有新的请求也无法执行,必须要等阻塞结束后才能执行后续的请求,造成了资源的极大的浪费
异步在遇到一些外界因素发生阻塞时会暂停该任务的执行转而执行其他的任务(该任务进入等待队列,等阻塞结束所有条件满足继续执行),异步不会等待程序的执行,能够更加充分了利用系统资源。
4. 配置celery
(1)什么是celery?
Celery是一个功能完备即插即用的任务队列,Celery适用异步处理问题,比如发送邮件、文件上传,图像处理等等比较耗时的操作,我们可将其异步执行,这样用户不需要等待很久,提高用户体验
而且celery具有简单,易于使用和维护,有丰富的文档,高效,单个Celery进程每分钟可以处理数百万个任务,灵活,Celery中几乎每个部分都可以自定义扩展,Celery非常易于集成到一些web开发框架中的特特点。
附上官方文档地址:http://docs.celeryproject.org/en/latest/index.htm
(2)安装celery(注意安装环境)
pip install celery
5.celery的工作原理
通过这张图我们大致会了解到,celery的工作原理:
- 任务队列是一种跨线程、跨机器工作的一种机制
- 任务队列中包含任务的工作单元。有专门的工作进程持续不断的监视任务队列,并从中获得新的任务并处理
- Celery通过消息进行通信,通常使用一个叫broker(中间人)来协client(任务的发出者)和worker(任务的处理者)
- client发出消息到队列中,broker将队列中的信息派发给worker来处理
- 一个Celery系统可以包含很多的worker和broker,可增强横向扩展性和高可用性能
6.利用celery实现短信验证码/邮箱验证码的异步发送
(1)创建celery_task模块,目录结构如下图所示
main---->
Celery------>检测任务(broker)
config------>配置文件
tasks ------>代码的主体(worker)
(2)设置中间人
- 示例:此处演示Redis数据库作为中间人broker
- Celery需要一种解决消息的发送和接受的方式,我们把这种用来存储消息的的中间装置叫做message broker, 也可叫做消息中间人。
-
作为中间人,我们有几种方案可选择:
-
1.RabbitMQ
- RabbitMQ是一个功能完备,稳定的并且易于安装的broker. 它是生产环境中最优的选择。
-
使用RabbitMQ的细节参照以下链接:http://docs.celeryproject.org/en/latest/getting-started/brokers/rabbitmq.html#broker-rabbitmq
-
如果使用的是Ubuntu或者Debian发行版的Linux,可以直接通过命令安装RabbitMQ:
sudo apt-get install rabbitmq-server
-
安装完毕之后,RabbitMQ-server服务器就已经在后台运行。
-
如果用的并不是Ubuntu或Debian, 可以在以下网址:
http://www.rabbitmq.com/download.html
去查找自己所需要的版本软件。
-
2.Redis
- Redis也是一款功能完备的broker可选项,但是其更可能因意外中断或者电源故障导致数据丢失的情况。
- 关于是由那个Redis作为Broker,可访下面网址:http://docs.celeryproject.org/en/latest/getting-started/brokers/redis.html#broker-redis
-
我们采用Redis方式
(3)编写代码:
main.py
from celery import Celery import os #导入django的配置 # os.getenv("变量名") 获取环境变量 # os.environ['变量名'] 创建环境变量 if not os.getenv('DJANGO_SETTINGS_MODULE'): os.environ['DJANGO_SETTINGS_MODULE'] = 'meiduo.settings' # 创建app对象 # 声明主文件入口(当前模块的主模块名称) app = Celery('celery_tasks') # 引入配置文件 app.config_from_object('celery_tasks.config') # 创建任务并启动监测 app.autodiscover_tasks(['celery_tasks.sms'])
config.py
# 配置队列信息,将celery的队列存储到数据库redis的14号数据库中 # 讲执行的结果存储到redis15好数据库中 broker_url = "redis://127.0.0.1/14" result_backend = "redis://127.0.0.1/15"
tasks
""" 注意该文件的名必须是tasks,不然 main无法识别 """ from libs.yuntongxun.sms import CCP from celery_tasks.main import app # 必须要用app.task装饰,可以设置name设置名称 @app.task(name='send_sms_code') def send_sms_code(mobile,smscode): ccp = CCP() ccp.send_template_sms(mobile, [smscode, 5], 1)
7.测试
在虚拟环境中添加指令执行(pycahrm-终端)
celery -A celery对象的路径 worker -l info celery -A celery_tasks.main worker -l info
这样我们就能实现短信验证码的异步发送了(邮箱验证一样)