简单使用Celery
⚠️ 请关注公众号“朋蛋”
1 介绍
Python异步耗时任务的框架有celery、RQ (Redis Queue)、 Dramatiq、ARQ、huey、funboost等,其中比较成熟的是celery和RQ (Redis Queue)。
Celery 功能强大的“瑞士军刀”,是一个成熟、功能全面的分布式任务队列系统。它支持多种消息代理和后端,适合构建复杂、大规模的应用,以其灵活性和强大功能而闻名。
RQ轻量级的“精致小刀”,基于 Redis,上手极快,配置简单,非常适合中小型项目或快速开发。充分利用 Redis 的数据结构,实现了一个非常直观的任务队列。它是一个 Python 分布式任务处理库,更加轻量级和简单,但它是纯粹的多进程模型,每个 Worker 是一个独立的进程。
celery
# 官网地址
https://docs.celeryq.dev/en/stable/index.html
# Github地址
https://github.com/celery/celery
RQ (Redis Queue)
# 官网地址
https://python-rq.org/
# Github地址
https://github.com/rq/rq/
Dramatiq是一个用于 Python 的分布式任务处理库。它的设计哲学与 Celery 类似,但强调的是简洁、可靠以及易用性,同时避免 Celery 那种复杂的配置和依赖,它的并发模型采用线程与进程混合的模型,并发性能较高。
# 开发文档
https://dramatiq.io/
# Github地址
https://github.com/Bogdanp/dramatiq
ARQ(Asynchronous RQ)是基于Redis(不支持其他组件)和 asyncio 的高性能 Python 异步任务队列。它专为现代异步应用设计,支持优先级队列、延迟任务、任务重试等功能。
# 开发文档
https://arq-docs.helpmanual.io/
# Github
https://github.com/python-arq/arq
安装celery
pip install "celery[librabbitmq,redis,auth,msgpack]"
docker创建Redis容器
docker run -d \
--name my-redis \
-p 6379:6379 \
-e REDIS_PASSWORD=123456 \
redis:6.2.2 redis-server --requirepass 123456
2 Python实现
2.1 消费任务
consumer_task.py
# consumer_task.py
from celery import Celery
# 创建 Celery 实例
app_cel = Celery(
# 标识名称
'myapp',
# 消息代理
broker='redis://:123456@192.168.108.147:6379/1',
# 存储数据
backend='redis://:123456@192.168.108.147:6379/2',
# 启动线程
worker_pool="solo"
)
# 执行耗时任务
@app_cel.task
def consumer_data(data: str):
duration = 3
print(f"任务开始,将持续 {duration} 秒")
print(data)
data_str = data + "-consumer"
print("任务完成")
return data_str
在终端中执行任务,consumer_task是文件名。
celery -A consumer_task worker -l INFO

2.2 生产者
producer_task.py
# producer_task.py
import time
from consumer_task import consumer_data
def producer_msg():
# 发送消息
for i in range(3):
time.sleep(1)
res = consumer_data.delay("data-"+ str(i))
print(res.get())
if __name__ == '__main__':
producer_msg()
执行生产者

消费者结果

2.3 Celery配置
Celery的配置很复杂,
# 针对多协程时需先打补丁
from gevent import monkey
# 设置猴子补丁
monkey.patch_all()
from celery import Celery
def _init_celery() -> Celery:
# 设置Redis基础信息,自己添加配置信息
redis_base_uri = "redis://:"+config_info.get("redis", "password")+"@"+config_info.get("redis", "host")+":"+config_info.get("redis", "port")
# 初始化APP
app = Celery(
main="celtask",
broker=redis_base_uri+"/0",
backend=redis_base_uri+"/0"
)
# 配置参数
app.conf.update(
# 修改并发任务的工作池,主要包括:prefork(默认)、eventlet和gevent、threads、solo
# prefork:多进程,用于CPU密集型;
# eventlet和gevent: 多协程,用于IO密集型,eventlet和gevent是两个不同的协程框架;
# threads:多进程,处于多协程和多进程之间;
# solo: 单线程,用于调试和测试;
# 因为该项目多用于IO型,因此设置为gevent
worker_pool="gevent",
# 设置并发数量
worker_concurrency=100,
# 预取任务数量,避免任务预取过多
worker_prefetch_multiplier=1,
# 忽略任务结果,如果不需要知道结果,可以设置这个值,并把下面的注释
task_ignore_result=True,
# # 任务执行状态在redis保留时间,默认24小时
# # 设置为半小时(30分钟=1800秒)
# result_expires=1800,
# 延迟确认
task_acks_late=True,
# 跟踪任务启动状态
task_track_started=True,
# 避免多个Celery服务同时使用1个Redis数据库,避免冲突
# 如果不考虑多个服务,可以注释下面的代码
# 修改默认消息队列
task_default_queue="app_queue"
)
return app
# 获取app
celapp = _init_celery()
132



被折叠的 条评论
为什么被折叠?



