1.celery的简介
celery是一个基于分布式消息传输的异步任务队列,它专注于实时处理,同时也支持任务调度。它的执行单元为任务(task),利用多线程,如Eventlet,gevent等,它们能被并发地执行在单个或多个职程服务器(worker servers)上。任务能异步执行(后台运行)或同步执行(等待任务完成)。
在生产系统中,celery能够一天处理上百万的任务。它的完整架构图如下:
组件介绍:
- Producer:调用了Celery提供的API、函数或者装饰器而产生任务并交给任务队列处理的都是任务生产者。
- Celery Beat:任务调度器,Beat进程会读取配置文件的内容,周期性地将配置中到期需要执行的任务发送给任务队列。
- Broker:消息代理,又称消息中间件,接受任务生产者发送过来的任务消息,存进队列再按序分发给任务消费方(通常是消息队列或者数据库)。Celery目前支持RabbitMQ、Redis、MongoDB、Beanstalk、SQLAlchemy、Zookeeper等作为消息代理,但适用于生产环境的只有RabbitMQ和Redis, 官方推荐 RabbitMQ。
- Celery Worker:执行任务的消费者,通常会在多台服务器运行多个消费者来提高执行效率。
- Result Backend:任务处理完后保存状态信息和结果,以供查询。Celery默认已支持Redis、RabbitMQ、MongoDB、Django ORM、SQLAlchemy等方式。
在客户端和消费者之间传输数据需要序列化和反序列化。 Celery 支出的序列化方案如下所示:
库: pip install celery
2.开发
celery的应用开发涉及四个部分
-
celery 实例初始化
-
任务的定义(定时和实时任务)
-
任务worker的启动
-
任务的调用
项目目录
实例化:
celery的实例化,主要包括执行Broker和backend的访问方式,任务模块的申明等
# app_test.py
from celery import Celery
app = Celery('demo_celery', include=['demo_celery.tasks'])
app.config_from_object('demo_celery.celeryconfig')
if __name__ == '__main__':
app.start()
#celeryconfig.py
BROKER_URL = 'redis://localhost' # 使用Redis作为消息代理
CELERY_RESULT_BACKEND = 'redis://localhost:6379/0' # 把任务结果存在了Redis
CELERY_TASK_SERIALIZER = 'msgpack' # 任务序列化和反序列化使用msgpack方案
CELERY_RESULT_SERIALIZER = 'json' # 结果序列化方案
CELERY_TASK_RESULT_EXPIRES = 60 * 60 * 24 # 任务过期时间
CELERY_ACCEPT_CONTENT = ['json', 'msgpack'] # 指定接受的内容类型
任务定义:
#task.py
import time
from demo_celery.app_test import app
@app.task #通过task装饰器声明celery任务
def add(x, y):
time.sleep(1)
return x + y
启动:
# -A wedo为应用模块
# -l为日志level
# -c 为进程数
celery -A demo_celery.app_test worker -l info -P eventlet
# 后台启动
nohup celery -A demo_celery.app_test worker -l info -P eventlet > ./log.log 2>&1
任务调用:
from demo_celery.tasks import add
import time
t1 = time.time()
r1 = add.delay(1, 2)
r2 = add.delay(2, 4)
r3 = add.delay(3, 6)
r4 = add.delay(4, 8)
r5 = add.delay(5, 10)
r_list = [r1, r2, r3, r4, r5]
for r in r_list:
while not r.ready():
pass
print(r.result)
3.分布式
将同样的代码部署在不同的机器上,使用相同的启动命令就可以
4.redis中存放的结果
#tasks代码
import time
from demo_celery.app_test import app
@app.task
def add(x, y):
time.sleep(1)
return x + y
#调用代码
调用方法:
1. delay()
delay是apply_async的封装,apply_async可以支持更多的任务调用配置
2.apply_async()
eta: 调用定时任务的参数
from demo_celery.tasks import add
import time
t1 = time.time()
r1 = add.delay(1, 2)
r2 = add.delay(2, 4)
r3 = add.delay(3, 6)
r4 = add.delay(4, 8)
r5 = add.delay(5, 10)
#调用后redis中存放有对应的记录
5.定时任务、延时任务、周期任务
定时任务-调用方法中传入时间即可
time_loc = datetime(2024,3,30,11,40,59)
time_user_define = datetime.utcfromtimestamp(time_loc.timestamp())
r6 = demo_0.apply_async(args=('测试定时任务',),eta=time_user_define)
延时任务(在当前时间上加自己需要的延时,同定人任务一样调用)
周期性任务
celeryconfig.py中增加周期任务配置
# 周期性任务配置
CELERYBEAT_SCHEDULE = {
"task1": {
"task": "demo_celery.schedule_task.func_0", #执行的函数
"schedule": crontab(minute="*/1"), # every minute 每分钟执行
"args": ('测试周期任务0',) # # 任务函数参数
},
"task2": {
"task": "demo_celery.schedule_task.func_1",
"schedule": crontab(minute=0, hour="*/1"), # every minute 每小时执行
"args": ('测试周期任务1',)
},
}
周期任务启动命令
在启动常规celery进程前,需要启动周期任务命令
celery -A demo_celery.app_test beat
6.指定队列调度,队列优先级
队列与路由配置
# 配置 queue 队列
CELERY_QUEUES = (
Queue('default', routing_key='default'),
Queue('queue_item', routing_key='apps.item.tasks'),
Queue('queue_daily', routing_key='apps.daily.tasks'),
)
# 配置每一个Task的Router
CELERY_ROUTES = {
'apps.item.tasks.event_list': {
'queue': 'queue_item',
'routing_key': 'apps.item.tasks',
},
'apps.item.tasks.actual_personday': {
'queue': 'queue_item',
'routing_key': 'apps.item.tasks',
},
'apps.item.tasks.reset_progress': {
'queue': 'queue_item',
'routing_key': 'apps.item.tasks',
},
'apps.daily.tasks.repeat_rate': {
'queue': 'queue_daily',
'routing_key': 'apps.daily.tasks',
},
}
启动命令
通过在不同机器上指定不同的队列启动 可以达到指定任务到指定执行机行执行
celery -A projectName worker -E -l info -n worker_daily -Q queue_daily
celery -A projectName worker -E -l info -n worker_item -Q queue_item
队列优先级
CELERY_QUEUES = (
Queue('default', routing_key='default'),
Queue('queue_item', routing_key='apps.item.tasks',),
queue_arguments={'x-max-priority': 10}
)
指定优先级调度
taskA.delay(queue='queue_item',priority=5)
taskB.delay(queue='queue_item',priority=10)
Celery进阶,多队列,Flower监控, Supervistor进程管理_celery-flower的登录密码在哪里设置-CSDN博客
7.进程管理 -- supervisor
推荐使用进程管理工具supervisor管理celery进程,保证服务的可靠性
8.报错解决:
Celery ValueError: not enough values to unpack (expected 3, got 0)-CSDN博客
9.参考:
任务队列神器:Celery 入门到进阶指南-腾讯云开发者社区-腾讯云
一文读懂 Python 分布式任务队列 celery (qq.com)
Celery 简介 — Celery 3.1.7 文档 (jinkan.org)
简介 - Celery 中文手册 (celerycn.io)
Celery笔记一之celery介绍、启动和运行结果跟踪 - 知乎 (zhihu.com)