==Celery安装== celery,分布式异步任务队列 eventlet,并发网络库 gevent 协程库
pip install celery==4.4.7
pip install eventlet==0.26.1
==Celery介绍== Celery中文手册 Celery 是一个 基于python的分布式异步任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery, 举几个实例场景:
异步任务:将==耗时==的操作任务提交给Celery异步执行,比如发送短信/邮件、消息推送、音频处理等等
做一个定时任务,比如每天定时执行爬虫爬取指定内容
还可以使用celery实现简单的分布式爬虫系统等等
Celery 在执行任务时需要通过一个==消息中间件==(Broker)来接收和发送任务消息,以及存储任务结果
Celery有以下优点:
简单:Celery 易于使用和维护,并且它 不需要配置文件 ,并且配置和使用还是比较简单的
高可用:当任务执行失败或执行过程中发生连接中断,celery 会自动尝试重新执行任务
快速:单个 Celery 进程每分钟可处理数以百万计的任务,而保持往返延迟在亚毫秒级
灵活: Celery 几乎所有部分都可以扩展或单独使用,各个部分可以自定义。
==celery核心==
1、Task
任务(Task)就是你要做的事情,例如一个注册流程里面有很多任务,给用户发验证邮件就是一个任务,这种耗时任务
可以交给Celery去处理,还有一种任务是定时任务
,比如每天定时统计网站的注册人数,这个也可以交给Celery周期性的处理。
2、Broker
Broker 的中文意思是经纪人,指为市场上买卖双方提供中介服务的人。在Celery中它介于生产者和消费者之间经纪人,这个角色相当于数据结构中的队列。例如一个Web系统中,生产者是处理核心业务的Web程序,业务中可能会产生一些耗时的任务,比如短信,生产者会将任务发送给 Broker,就是把这个任务暂时放到队列中,等待消费者来处理。消费者是 Worker,是专门用于执行任务的后台服务。Worker 将实时监控队列中是否有新的任务,如果有就拿出来进行处理。Celery 本身不提供队列服务,一般用 Redis 或者 RabbitMQ 来扮演 Broker 的角色
3、Worker
Worker 就是那个一直在后台执行任务的人,也称为任务的消费者,它会实时地监控队列中有没有任务,如果有就立即取出来执行。
4、Beat
Beat 是一个定时任务调度器,它会根据配置定时将任务发送给 Broker,等待 Worker 来消费。
5、Backend
Backend 用于保存任务的执行结果,每个任务都有返回值,比如发送邮件的服务会告诉我们有没有发送成功,这个结果就是存在Backend中,当然我们并不总是要关心任务的执行结果。
官方文档: 简介 - Celery 中文手册
==创建worker==
创建一个文件laufing.py,内部编写如下代码
#实例化对象 from celery import Celery # 第一个参数worker name # broker 代理,消息中间件 app = Celery("myworker", broker="redis://:laufing@localhost:6379/4") #也可以app.conf.broker_url = "xxxx" #创建任务函数 @app.task def task1(): print("正在执行任务...")
前台启动worker进程。 在cmd 命令行输入如下:
# windows 下需要加-P eventlet 或者 -P gevent #因为celery 4.x 对window支持的不太好 celery -A laufing worker --loglevel=info -P eventlet #linux celery -A laufing worker -l info
模拟django发送任务
ipython中模拟发送任务:在laufing.py的同级目录打开一个cmd命令行。
创建一个laufing.py文件,并创建worker
from celery import Celery app = Celery("worker2", broker="redis://:laufing@localhost:6379/4", backend="redis://:laufing@localhost:6379/5") @app.task def task1(a, b): print("简单求和") return a + b @app.task def task2(a, b): print("2-s后求和") time.sleep(20) return a + b
前台启动worker
#window celery -A laufing worker -l info -P eventlet
发送任务,并获取结果 ipython中测试如下:
from laufing import task1, task2 r1 = task1.delay(3, 5) # 发送任务 r1.result r2 = task2.delay(4, 7) #发送任务,并立即执行下一行,不会阻塞 r2.result # worker来执行task,返回结果后才可以拿到
分布式的worker:
只需在多个主机上启动该laufing下的worker即可, 每一个worker进程都是并发处理任务
在django项目主应用下创建celery.py文件,配置以下内容:
# celery.py文件 import os from celery import Celery from django.conf import settings # 为celery配置环境变量,识别和加载django的配置文件 # 因为worker是脱离django启动的,且依赖其配置 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mdpro.settings') # 主应用 # 创建celery实例 app = Celery('mdpro') # 指定celery消息队列的配置 app.config_from_object('mdpro.config', namespace='CELERY') #也可以app.conf.update(BROKER_URL="XXX") # 从所有的django-app中加载任务 app.autodiscover_tasks(settings.INSTALLED_APPS)
在django项目主应用mdpro下创建config.py文件,配置以下内容:
# 消息中间人broker设置 broker_url = 'redis://127.0.0.1:6379/15' #不能写localhost # 结果存储设置 result_backend = 'redis://127.0.0.1:6379/14'
在django项目其他应用下,这里是users,创建tasks.py
# tasks.py from ronglian_sms_sdk import SmsSDK from mdpro.celery import app import json import random accId = '8a216da8757784cd017586e2a0280446' accToken = '92fbee01e5474904a437b062ea43baf4' appId = '8a216da8757784cd017586e2a0f4044c' @app.task def send_message(phone, msg_code): sdk = SmsSDK(accId, accToken, appId) tid = '1' # 容联云分配的一个测试短信验证码模版 mobile = phone # 接收短信的手机号 datas = (msg_code, '5') resp = sdk.sendMessage(tid, mobile, datas) resp_json = json.loads(resp) return resp_json
视图中发送异步任务
class GenerateVerifyCode(APIView): """ 生成手机号验证码 """ def post(self, request): code_id = request.data.get('code_id') phone = request.data.get('phone') msg_code = '%06d' % random.randint(0, 1000000) #发送任务 res = send_message.delay(phone, msg_code) # 0或者 11111 print("异步队列的响应", res) # sms_redis.set(code_id, msg_code, ex=300) return Response({'msg': 'OK', 'code': 200})
启动celery
# windows系统下启动 celery -A mdpro worker -l info -P eventlet # mac下启动, celery -A mdpro worker -l info