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('任务已经开始被执行')

 

posted @ 2019-04-19 00:39  星牧  阅读(1375)  评论(0编辑  收藏  举报