Celery消息队列,Celery单任务异步提交使用,Celery多任务异步提交使用,Celery执行定时任务
简介
Celery是一个简单、灵活且可靠的,处理大量消息的分布式系统
专注于实时处理的异步任务队列,同时也支持任务调度
架构图
......
Celery使用场景
异步任务:将耗时操作任务提交给Celery去异步执行,比如发送短信/邮件、消息推送、音视频处理等等
定时任务:定时执行某件事情,比如每天数据统计
安装
pip install eventlet pip install celery 消息中间件:RabbitMQ/Redis app=Celery('任务名',backend='xxx',broker='xxx')
Celery单任务异步提交使用
创建一个任意项目
在项目里创建一个 celery_app_task.py 文件 (相当于雇工人干活)
import celery import time # 消息队列存储在redis中,连接redis # broker='redis://127.0.0.1:6379/2' 不加密码 # backend = 'redis://:123456@127.0.0.1:6379/1' 有密码连接方式 backend = 'redis://27.0.0.1:6379/1' # 消息存储redis文件1 broker = 'redis://127.0.0.1:6379/2' # 结果存储redis文件2 # 第一个参数,给celery命个名,可以任意命名 cel = celery.Celery('test', backend=backend, broker=broker) # 往下写任务(发邮件等一系列任务) @cel.task # 生成任务,以后需要提交的任务写这里 def add(x, y): return x + y
创建一个 add_task.py 文件
from Django项目.day32.celerytest.celery_app_task import add result = add.delay(4, 5) # celery异步提交任务到消息中间件里 print(result.id)
创建一个 result.py 文件 (查看结果)
from celery.result import AsyncResult from Django项目.day32.celerytest.celery_app_task import cel async = AsyncResult(id="e919d97d-2938-4d0f-9265-fd8237dc2aa3", app=cel) # 注意 id 参数的值为add_task.py执行的结果 if async.successful(): result = async.get() print(result) # result.forget() # 将结果删除 elif async.failed(): print('执行失败') elif async.status == 'PENDING': print('任务等待中被执行') elif async.status == 'RETRY': print('任务异常后正在重试') elif async.status == 'STARTED': print('任务已经开始被执行')
celery提交单任务异步执行顺序
1. 先执行 add.py 文件 2. 在执行 linux系统下:celery worker -A celery_app_task -l info windows系统下:celery worker -A celery_app_task -l info -P eventlet 3. 最后执行 result.py # 查看结果
Celery多任务异步提交使用
多任务结构图
pro_cel ├── celery_task# celery相关文件夹 │ ├── celery.py # celery连接和配置相关文件,必须叫这个名字 │ └── tasks1.py # 所有任务函数 │ └── tasks2.py # 所有任务函数 ├── check_result.py # 检查结果 └── send_task.py # 触发任务
按照结构图创建文件夹celery_task
在celery_task里面创建 celery.py(必须取名为celery) 文件,(雇多个工人)子路径
import celery import time # 消息队列存储在redis中,连接redis # broker='redis://127.0.0.1:6379/2' 不加密码 # backend = 'redis://:123456@127.0.0.1:6379/1' 有密码连接方式 # 消息存储redis文件1 backend = 'redis://127.0.0.1:6379/1' # 结果存储redis文件2 broker = 'redis://127.0.0.1:6379/2' # 第一个参数,给celery命个名,可以任意命名 cel = celery.Celery('test', backend=backend, broker=broker, include=['celery_task.task1', 'celery_task.task2']) # 异步执行多个任务(雇了多个工人) # 处理时区问题 # 时区 cel.conf.timezone = 'Asia/Shanghai' # 是否使用UTC cel.conf.enable_utc = False
雇佣工作工人,linux系统下:celery worker -A celery_app_task -l info
雇佣工作工人,windows系统下:celery worker -A celery_app_task -l info -P eventlet
创建task1.py文件,子路径
from celery_task.celery import cel @cel.task # 生成task1的任务 def add(x, y): return x + y
创建task2.py文件,子路经
from celery_task.celery import cel @cel.task # 生成task2的任务 def add(x, y): return x - y
创建send_task.py文件(Celery的根路径下),添加到消息中间件里
from celery_task import task1,task2 result1 = task1.add.delay(4, 5) # celery异步提普通交任务1到消息中间件里 print(result1.id) result2 = task2.add.delay(4, 5) # celery异步提交普通任务2到消息中间件里 print(result2.id)
创建check_result.py文件(Celery的根路径下),拿到任务执行结果
from celery.result import AsyncResult from celery_task.celery import cel async = AsyncResult(id="cbe2cb11-259a-4877-850d-8e736dd76eaf", app=cel) if async.successful(): result = async.get() print(result) # result.forget() # 将结果删除 elif async.failed(): print('执行失败') elif async.status == 'PENDING': print('任务等待中被执行') elif async.status == 'RETRY': print('任务异常后正在重试') elif async.status == 'STARTED': print('任务已经开始被执行')
celery提交多任务异步执行顺序
1.先执行 send_task.py 文件 # 一次性提交多个任务 2.在执行 linux系统下:celery worker -A celery_app_task -l info windows系统下:celery worker -A celery_app_task -l info -P eventlet 3.最后执行 check_result.py # 查看结果
Celery执行定时任务
Celery架构图
创建send_task.py文件,跟路径,提交定时任务
from celery_task import task1, task2 from datetime import datetime # 方法一 # 提交定时任务,设置定时任务执行时间 # v1 = datetime(2019, 4, 20, 16, 50, 50) # 参数为年月日时分秒 # print(v1)# 转成utc时间 # v2 = datetime.utcfromtimestamp(v1.timestamp()) # print(v2) # result = task1.add.apply_async(args=[1, 3], eta=v2) # 提交定时任务 # print(result.id) # 方法二(推荐) ctime = datetime.now() # 默认用utc时间 utc_ctime = datetime.utcfromtimestamp(ctime.timestamp()) from datetime import timedelta time_delay = timedelta(seconds=10) # seconds往后延迟多少秒的时间片段
task_time = utc_ctime + time_delay # 使用apply_async并设定时间,
result = task1.add.apply_async(args=[4, 3], eta=task_time) # 提交定时任务,eta指定执行时间
print(result.id)
创建celery_task文件夹
在celery_task文件夹里,创建celery.py文件,子路径,雇佣处理定时任务的工人
from celery import Celery import time from datetime import timedelta # from celery.schedules import crontab # 消息队列存储在redis中,连接redis # broker='redis://127.0.0.1:6379/2' 不加密码 # backend = 'redis://:123456@127.0.0.1:6379/1' 有密码连接方式 backend = 'redis://127.0.0.1:6379/1' # 消息存储redis文件1 broker = 'redis://127.0.0.1:6379/2' # 结果存储redis文件2 # 第一个参数,给celery命个名,可以任意命名 cel = Celery('test', backend=backend, broker=broker,
# 包含以下两个任务文件,去相应的py文件中找任务,对多个任务做分类
include=['celery_task.tasks1','celery_task.tasks2'])
# 处理时区问题 # 时区 cel.conf.timezone = 'Asia/Shanghai' # 是否使用UTC cel.conf.enable_utc = False
# 雇佣工人帮我提交任务到消息队列里 cel.conf.beat_schedule = { # 名字随意命名 'add-every-10-seconds': { # 执行tasks1下的test_celery函数 'task': 'celery_task.task1.add', # 每隔2秒执行一次 # 'schedule': 1.0, # 'schedule': crontab(minute="*/1"), # 每分钟执行一次,也可以每小时等 'schedule': timedelta(seconds=2), 'args': ('test',) # 给执行函数传递参数 }
# 每年每月等提交任务到消息队列里 # 'add-every-12-seconds': { # 'task': 'celery_task.tasks1.test_celery', # # 每年4月11号,8点42分执行 # 'schedule': crontab(minute=42, hour=8, day_of_month=11, month_of_year=4), # 每年4月11日8点42分提交任务到消息队列里 # 'schedule': crontab(minute=42, hour=8), # 每天8点42分提交任务到消息队列里 # 'args': (16, 16) # }, }
雇佣提交定时任务到消息队列里命令:celery beat -A celery_task -l info
雇佣工作工人,linux系统下:celery worker -A celery_app_task -l info
雇佣工作工人windows系统下:celery worker -A celery_app_task -l info -P eventlet
创建task2.py文件,子路经,生成任务2
from celery_task.celery import cel @cel.task # 生成task2的任务 def add(x, y): return x + y
创建task1.py文件,子路经,生成任务1
from celery_task.celery import cel @cel.task # 生成task1的任务 def add(x, y): return x - y
创建check_result.py文件,跟路径,查看定时任务执行结果
from celery.result import AsyncResult from celery_task.celery import cel async = AsyncResult(id="e6742e1f-a6a4-43b8-915a-a221e33db756", app=cel) # id为提交任务时给我的id,send_task.py里的result if async.successful(): result = async.get() print(result) # result.forget() # 将结果删除 elif async.failed(): print('执行失败') elif async.status == 'PENDING': print('任务等待中被执行') elif async.status == 'RETRY': print('任务异常后正在重试') elif async.status == 'STARTED': print('任务已经开始被执行')