celery是异步任务比较流行的一个框架,我们通常不希望系统在一些耗时任务中卡主(比如发送邮件,生成报告,记录日志等等),所以将这些任务丢到后台异步进行是一个不错的方法。
celery中文文档:http://celery.xgqyq.com/
官方文档:https://docs.celeryq.dev/en/latest/getting-started/introduction.html
Celery入门
先不考虑在fastapi和Django中使用它,先写一个纯celery 的任务,让它正常运行
安装依赖
Celery
需要用到中间件用来发送消息、存储结果数据。常用的包括rabbitmq
以及redis
。我这里用到redis,所以需要提前装好。pip install celery
:本体pip install -U "celery[redis]"
:支持Redis需要安装额外的依赖pip install eventlet
:在windows环境下开发需要额外安装这个,不然会报错
代码
-
celery_app.py
from celery import Celery app = Celery("tasks", broker='redis://127.0.0.1:6379/0', backend='redis://127.0.0.1:6379/1') @app.task def add(x, y): return x + y
-
start_celery_app.py
from celery_app import add import time result = add.delay(12, 12) while not result.ready(): print(time.strftime("%H:%M:%S")) time.sleep(1) print(result.get()) print(result.successful())
执行
celery -A celery_app worker --loglevel=INFO -P eventlet
- 运行
start_celery_app.py
辅助工具
-
Flower 是一个基于 Web 的 Celery 监控工具,它可以为你提供一个直观的界面来监控和管理 Celery 集群的运行状况。
-
安装:
pip install flower
-
启动:
celery -A celery_app flower
-
进入:http://localhost:5555/
Celery的中间件解析
为什么用中间件
- Celery 的核心是任务队列,任务的生产者(Producer)和消费者(Worker)之间需要一个桥梁进行通信
- Celery 允许追踪任务的执行状态,中间件可以充当一个状态存储的角色
- 处理高并发和异步
- 一些中间件(例如 RabbitMQ)支持任务的 持久化存储
中间件的选择
关于中间件的选择,官网上是这么说的
Redis
非常适合快速传输小消息,且可以非常高效地获取任务调用的结果,但必须考虑可用于存储数据的内存限制,以及如何处理数据持久性RabbitMQ
处理较大的消息比Redis
更好,但是如果许多消息非常快速地进入,则扩展可能成为一个问题- 总结下:
redis
简单好用性能高,RabbitMQ
功能完整,持久性好
redis中的key含义
在上文中,有这么一行配置
app = Celery("tasks", broker='redis://127.0.0.1:6379/0', backend='redis://127.0.0.1:6379/1')
broker
是消息中间件,负责任务队列的管理和消息的传递,当调用delay()
提交任务时,任务会先被发布到 `broker``- ``backend` 是任务结果的存储后端,负责保存任务的执行结果和状态。
- 这两个可以使用一个db,我这里进行了分离
- 进入db0,发现库中生成了三个key,分别是
_kombu.binding.celery
,_kombu.binding.celery.pidbox
,_kombu.binding.celeryev
,这三个键对应了 Celery 核心功能的不同部分:
键名 | 功能 | 场景 |
---|---|---|
_kombu.binding.celery | 主任务队列绑定信息 | 用于任务的正常分发与处理 |
_kombu.binding.celery.pidbox | 控制命令队列绑定信息 | 用于控制命令的通信,当你使用 celery inspect 、celery control 或 celery status 等命令时,控制消息会通过这个队列传递到 Worker。 |
_kombu.binding.celeryev | 事件队列绑定信息 | 用于任务事件(如任务开始、完成、失败等)的广播和监控 |
- 每执行完一个任务后,进入db1,就会多了一个key,类型是string,里面存储了执行的结果,是个json字符串,很好理解:
{
"status": "SUCCESS",
"result": 24,
"traceback": null,
"children": [],
"date_done": "2024-12-12T09:42:36.148302+00:00",
"task_id": "0404b25a-097e-47ae-b509-78c6042ab6b3"
}
Celery的配置
- 官网将celery比作电器,不需要太多配置即可运行,当你需要的时候,就可以打开后面的盖子,里面有很多滑块、拨盘和按钮:这就是配置。
- 实际使用配置很方便,既可以单个配置,也可以批量配置,既可以直接在应用程序上设置配置,也可以使用专用配置模块进行设置
在应用中直接配置
from celery import Celery
app = Celery("tasks", broker='redis://127.0.0.1:6379/0', backend='redis://127.0.0.1:6379/1')
# 既可以单个配置
# 这里修改了主任务队列的key,改成了_kombu.binding.celery:v1:default:task
app.conf.task_default_queue = 'celery:v1:default:task'
# 也可以批量配置
app.conf.update(
# 这里修改了结果存储的key前缀,改成了v1:prefix:.....
result_backend_transport_options={'global_keyprefix': 'v1:prefix:'},
# 修改时区
timezone='Asia/Shanghai'
)
@app.task
def add(x, y):
return x + y
导入配置文件
- 新建一个配置文件celeryconfig.py,就在当前目录
task_default_queue = 'celery:v2:default:task'
result_backend_transport_options = {'global_keyprefix': 'v2:prefix:'}
accept_content = ['json']
timezone = 'Asia/shanghai'
- 导入配置
app.config_from_object('celeryconfig')