celery异步任务队列

1. celery简介

   celery是一个强大的分布式任务队列的异步处理框架,它可以让任务的执行完全脱离主程序,甚至可以被分配到其他主机上运行。通常用来实现实时处理的异步任务队列,和定时任务调度。
异步任务:将耗时任务提交给celery去异步执行,比如发送短信/邮件、消息推送、音视频处理等。
定时任务:定时执行某件事情,比如每天数据统计。

   celery架构由三部分组成,消息中间件(message broker),任务执行单元(worker)和任务执行结果存储(result backend)组成。
celery异步任务队列_第1张图片

producer:任务生产者,调用了celery提供的api、函数或者装饰器,而产生任务并交给任务队列处理的都是生产者。

broker:消息中间件,接受任务生产者发送过来的任务消息,存进任务队列并按顺序分发给任务消费方。celery本身不提供消息服务,但是可以方便的和第三方提供的消息中间件集成,包括RabbitMQ, Redis等。

worker:执行任务的消费者,通常在多台服务器上运行多个消费者来提高执行效率。

result backend:任务结果存储,用来存储Worker执行的任务结果,Celery支持以不同方式存储任务的结果,包括RabbitMQ, redis等。

celery beat:任务调度器,beat进程会周期性地将配置中到期需要执行的任务发送给任务队列。

2. celery安装

pip install celery
pip install eventlet	# 在windows跑任务时需要eventlet,通过协程实现并发

3. celery用于异步任务处理

项目目录结构
flask_celery
│ get_async_result.py
│ produce_task.py
│─async_tasks
│ │ create_celery.py
│ │ task_email.py

创建celery对象
create_celery.py

from celery import Celery

celery_app = Celery("celery_demo",
                    broker="redis://127.0.0.1:6379/1",
                    backend="redis://127.0.0.1:6379/2",
                    include=["async_tasks.task_email", "async_tasks.task_msg"]
                    )

创建异步任务
task_email.py

import time
from async_tasks.create_celery import celery_app

@celery_app.task
def send_email(name):
    print(f"start to send email to {name}")
    time.sleep(5)
    return f"send email to {name} ok !"

主流程调异步任务
produce_task.py

from async_tasks.task_email import send_email

result_email = send_email.delay("lisi")
print(f"send email task id is {result_email}")

获取异步任务结果
get_async_result.py

from celery.result import AsyncResult
from async_tasks.create_celery import celery_app

# 这块的task_id,不是produce_task.py的result_email,result_email是AsyncResult类,传参应该使用result_email.id属性
async_result = AsyncResult(task_id, app=celery_app)	

if async_result.successful():
    task_result = async_result.get()
    print("task exec succeed")
    print(task_result)
elif async_result.failed():
    print("task exec failed")
elif async_result.status == "PENDING":
    print("task exec is waiting")
elif async_result.status == "RETRY":
    print("task exec is retrying after fail")
elif async_result.result == "STARTED":
    print("task exec is ready to exec")
else:
    print("others")

命令行开启worker

cd flask_celery		# 先进入项目跟目录
celery -A async_tasks.create_celery worker -l info -P eventlet 	# 开启worker
注意:
	如果不进入到项目跟目录,那么在实例化Celery的include参数要从项目根目录开始,命令行 -A 后面的参数也要从项目根目录开始,否则报错:没有xxx模块

4. celery用于定时任务处理

项目目录结构
flask_celery
│ timing_task.py
│─async_tasks
│ │ create_celery.py
│ │ task_msg.py

增加定时任务
task_msg.py

import time
from async_tasks.create_celery import celery_app

@celery_app.task
def send_msg(id):
    print(f"start to send msg to {id}")
    time.sleep(5)
    return f"send msg to {id} ok !"

创建celery对象,并制定定时策略
create_celery.py

from datetime import timedelta

from celery import Celery
from celery.schedules import crontab

celery_app = Celery("celery_demo",
                    broker="redis://127.0.0.1:6379/1",
                    backend="redis://127.0.0.1:6379/2",
                    include=["async_tasks.task_email", "async_tasks.task_msg"])

celery_app.conf.timezone = "Asia/Shanghai"
celery_app.conf.enable_utc = False

celery_app.conf.beat_schedule = {
    # 定时任务名字
    "add_timing_email": {
        "task": "async_tasks.task_email.send_email",        # 要执行的定时任务函数, 必须到函数名
        # "schedule": 10,                                   # 每10秒执行一次
        # "schedule": crontab(minutes="*/10")               # crontab表达式
        "schedule": timedelta(seconds=10),                  # 间隔10秒
        "args": ("zhangsan", )
    },
    # 定时任务名字
    "add_timing_msg": {
        "task": "async_tasks.task_msg.send_msg",
        "schedule": crontab(minute="*/10"),
        "args": ("lisi",)
    }
}

也可以不制定定时策略,自己手写一个一次性执行的定时任务。
timing_task.py

from datetime import datetime

from async_tasks.task_msg import send_msg

t1 = datetime(2023, 5, 29, 11, 23, 00)
t2 = datetime.utcfromtimestamp(t1. timestamp())
result_msg = send_msg.apply_async(args=["zhangsan02"], eta=t2)      # eta参数必须传入utc时间
print(f"send msg task id is {result_msg}")

命令行启动worker

cd flask_celery		# 先进入项目跟目录
celery -A async_tasks.create_celery worker -l info -P eventlet 	# 开启worker
注意:
   	1. -A 后面的参数必须截至到生成celeryapp的文件名
	2. 如果不进入到项目跟目录,那么在实例化Celery的include参数要从项目根目录开始,命令行 -A 后面的参数也要从项目根目录开始,否则报错:没有xxx模块

命令行启动定时任务

celery -A async_tasks.create_celery beat -l info
注意事项和异步任务同理。

你可能感兴趣的:(flask,python,后端)