项目地址:GitHub - celery/celery: Distributed Task Queue (development branch)
文档地址:(3.1)入门 — Celery 3.1.7 文档
(5.1) Celery - Distributed Task Queue — Celery 5.3.1 documentation
celery不建议在windows下使用,Celery在4.0版本之后不再支持windows系统,如果要在windows下使用只能安装4.0以前的版本,并且需要安装geventlet或eventlet协程模块
什么是celery
celery是一个简单、灵活、可靠的,可以处理大量消息的分布式系统,专注于实时处理异步任务队列,同时也支持任务调度
Task
任务(Task) 就是你要做的事情,例如一个注册流程里面有很多任务,给用户发验证邮件、发送短信验证码等
Broker
Broker中文意思是经纪人,他介于生产者和消费者之间,相当于数据结构中的队列,Celery本身不提供队列服务,一般使用Redis或者RabbitMQ来扮演Broker
Worker
Worker就是在后台一直去执行任务的人,也称为任务的消费者,它会实时地监控队列中有没有任务[轮询],如果有就立即取出来执行
Beat
Beat是一个定时任务调度器,它会根据配置定时将任务发送给Broker,等待Worker来消费
Backend
Backend用户保存任务的执行结果,每个任务都会有返回值,比如发送邮件会返回是否成功,这个结果存储在Backend中
使用场景
celery是一个强大的分布式任务队列异步处理框架,它可以让任务脱离主程序执行,甚至可以分配到其他主机上执行,通常使用celery处理异步任务或者定时任务
异步任务 : 将耗时操作的任务交给celery,如发送邮件、短信、消息推送、音视频处理等
定时任务 : 定时执行某件事情,比如每天统计数据
celery运行原理
原理 : 就是django写的任务(Task)推送到Broker(任务队列)中,启动celery(Worker)不断对broker进行轮询,处理任务的结果存储到backend中,之后客户端视图会从结果队列把结果拿出来
客户端 : django代码写的task任务
broker : 任务队列(redis、rabbitMQ)
worker : celery提供进程
backend : 结果队列(redis、rabbitMQ)
一个celery系统可以包含很多的worker和broker
Celery本身不提供消息队列功能,但是可以很方便地和第三方提供的消息中间件进行集成,包括Redis、RabbitMQ、RocketMQ等
安装
pip install -U celery -i Simple Index
使用
celery单独使用
run.py文件内容
from celery import Celery
# 通过使用本机redis且没有密码,使用远程redis有密码格式为
# 'redis://:密码@ip:6379/1'
broker = 'redis://127.0.0.1:6379/1' # 任务储存
backend = 'redis://127.0.0.1:6379/2' # 结果存储,执行完之后结果放在这
# 创建出app对象
app = Celery(__name__, broker=broker, backend=backend)
# 任务通过装饰器@app.task进行装饰
@app.task
def add(x, y):
return x + y
task.py
# celery的任务必须写在tasks.py的文件中,别的文件名称不识别!!!
from mycelery.main import app
import time
import logging
log = logging.getLogger("django")
@app.task # name表示设置任务的名称,如果不填写,则默认使用函数名做为任务名
def send_sms(mobile):
"""发送短信"""
print("向手机号%s发送短信成功!"%mobile)
time.sleep(5)
return "send_sms OK"
@app.task # name表示设置任务的名称,如果不填写,则默认使用函数名做为任务名
def send_sms2(mobile):
print("向手机号%s发送短信成功!" % mobile)
time.sleep(5)
return "send_sms2 OK"
@app.task(name="send_sms3")
def send_sms3(x,y):
"""有结果的异步任务"""
print('任务:send_sms3执行了...')
return x+y
main.py
import os
from celery import Celery
# 实例化celery应用,第一个参数是自定义的一个实例名称,按变量名的命名规范来定义
app = Celery("test")
# 把celery和django进行组合,识别和加载django的配置文件
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'celeryPros.settings.dev')
# 通过app实例对象加载配置
app.config_from_object("mycelery.setting")
# 注册异步任务, 自动搜索并加载任务
# 参数必须必须是一个列表,里面的每一个任务都是任务的路径名称
# app.autodiscover_tasks(["任务1","任务2",....])
# 会自动识别到tasks.py中的异步任务
app.autodiscover_tasks(["mycelery.sms","mycelery.mail"])
# 启动Celery的终端命令
# 强烈建议切换目录到项目的根目录下启动celery!!
# celery -A mycelery.main worker --loglevel=info
setting.py
# 任务队列的链接地址
broker_url = 'redis://127.0.0.1:6379/14'
#
# # 结果队列的链接地址
result_backend = 'redis://127.0.0.1:6379/15'
produce.py
from mycelery.sms.tasks import send_sms2, send_sms3
# from mycelery.sms.tasks import send_sms, send_sms3
from datetime import datetime
import time
# delay(*arg, **kwargs)
# apply_async((arg,), {'kwarg': value}, countdown=60, expires=120)
# delay 表示马上按顺序来执行异步任务,在celrey的worker工作进程有空闲的就立刻执行
# 可以通过delay异步调用任务,可以没有参数
# delay(*arg, **kwargs)
# apply_async 让任务在后面指定时间后执行,时间单位:秒/s
# 任务名.apply_async(args=(参数1,参数2), countdown=定时时间)
# apply_async((arg,), {'kwarg': value}, countdown=60, expires=120)
# 根据返回结果,不管delay,还是apply_async的返回结果都一样的。
# result = send_sms2.delay(13894000789)
# print(result.id) # 返回一个UUID格式的任务唯一标志符,78fb827e-66f0-40fb-a81e-5faa4dbb3505
# time.sleep(5)
# print(result.status) # 查看当前任务的状态 SUCCESS表示成功!
ctime = datetime.now()
# 默认用utc时间
utc_ctime = datetime.utcfromtimestamp(ctime.timestamp())
from datetime import timedelta
time_delay = timedelta(seconds=10)
task_time = utc_ctime + time_delay
# 使用apply_async并设定时间
result = send_sms2.apply_async(args=["120"], eta=task_time)
print(result)
result2 = send_sms3.delay(3,3)
print(result2)
# 查看任务执行状态,执行完成(不管是否发生异常还是正常执行)返回True,未执行返回False
print(result2.ready())
# 如果任务出现异常,可以通过以下命令进行回溯
result2.traceback
from mycelery.main import app
from celery.result import AsyncResult
asy = AsyncResult(id=result, app=app)
# 是否正常执行完成,正常执行成功返回True,否则返回False
print(asy.successful())
# 执行成功打印结果
print(asy.get())
# 是否正常执行失败,失败返回True,否则返回False
print(asy.failed())
# 查看任务状态
print(asy.status)
# 执行状态一般有三种PENDING、RETRY、STARTED
运行步骤
终端执行命令启动worker : celery -A mycelery.main worker --loglevel=info
执行peoduce_task.py , 查看终端,并查看结果队列
celery集成到django框架
启动mycelery项目,访问接口127.0.0.1:8080/test
终端命令 : celery -A mycelery.main worker --loglevel=info
view.py
from django.shortcuts import render
# Create your views here.
from django.shortcuts import render,HttpResponse
from mycelery.mail.tasks import send_mail,send_mail2
from datetime import timedelta
from datetime import datetime
def test(request):
################################# 异步任务
# 1. 声明一个和celery一模一样的任务函数,但是我们可以导包来解决
# send_mail.delay("110qq.com")
# send_mail2.delay("119qq.com")
# send_sms.delay() 如果调用的任务函数没有参数,则不需要填写任何内容
################################# 定时任务
ctime = datetime.now()
# 默认用utc时间
utc_ctime = datetime.utcfromtimestamp(ctime.timestamp())
time_delay = timedelta(seconds=10)
task_time = utc_ctime + time_delay
result = send_mail.apply_async(["911", ], eta=task_time)
print("xiaofeizhe",result.id)
return HttpResponse('ok')
celery异步任务调用方法
delay(*args, **kwargs)
apply_async((*args,),{**kwargs:value}, countdown=60, expires=120)
delay:表示马上按照顺序执行异步任务(task.py),在celery的worker有空闲就会立刻执行
apply_async 让任务在后面指定时间后执行,时间单位:秒/s
任务名.apply_async(args=(参数1,参数2), countdown=定时时间)
出现错误情况
list模式 :当消息丢失或者消费失败,只能在消费之前把数据备份,之后配置base=class,class是一个类,类中写一些回调函数,on_failuer,on_success等,