celery介绍
Celery 是一个强大的分布式任务队列,主要包括三个部分消息中间件 Broker、任务执行单元 Worker、任务结果存储 Backend,它可以让任务的执行完全脱离主程序,甚至可以被分配到其他主机上运行。我们通常使用它来实现异步任务( async task )和定时任务( crontab )。 异步任务比如是发送邮件、或者文件上传, 图像处理等等一些比较耗时的操作 ,定时任务是需要在特定时间执行的任务。它的架构组成如下图:
任务队列
任务队列是一种跨线程、跨机器工作的一种机制.任务队列中包含称作任务的工作单元。有专门的工作进程持续不断的监视任务队列,并从中获得新的任务并处理.
任务模块
包含异步任务和定时任务。其中,异步任务通常在业务逻辑中被触发并发往任务队列,而定时任务由 Celery Beat 进程周期性地将任务发往任务队列。
消息中间件 Broker
Broker ,即为任务调度队列,接收任务生产者发来的消息(即任务),将任务存入队列。 Celery 本身不提供队列服务,官方推荐使用 RabbitMQ 和 Redis 等。
任务执行单元 Worker
Worker 是执行任务的处理单元,它实时监控消息队列,获取队列中调度的任务,并执行它。
任务结果存储 Backend
Backend 用于存储任务的执行结果,以供查询。同消息中间件一样,存储也可使用 RabbitMQ, Redis 和 MongoDB 等。
使用 Celery 实现定时任务的步骤:
- 创建一个 Celery 实例
- 发布任务:
celery A xxx beat
- 启动: celery -A celery_task worker --loglevel=info
- 存储结果
celery定时任务demo
- 文件目录结构(celery_test为项目名称目录)
-
celery配置文件:celeryconfig.py
from datetime import timedelta
broker_url = "redis://127.0.0.1:6379/2" # 使用redis存储任务队列
result_backend = "redis://127.0.0.1:6379/6" # 使用redis存储结果
task_serializer = 'json'
result_serializer = 'json'
accept_content = ['json']
timezone = "Asia/Shanghai" # 时区设置
worker_hijack_root_logger = False # celery默认开启自己的日志,可关闭自定义日志,不关闭自定义日志输出为空
result_expires = 60 * 60 * 24 # 存储结果过期时间(默认1天)
# 导入任务所在文件
imports = [
"celery_task.epp_scripts.t1", # 导入py文件
"celery_task.epp_scripts.t2",
]
# 需要执行任务的配置
beat_schedule = {
"test1": {
"task": "celery_task.epp_scripts.t1.test11", # 执行的函数
"schedule": timedelta(seconds=30), # 每30s执行
"args": () # 任务函数参数
},
"test2": {
"task": "celery_task.epp_scripts.t2.celery_run",
"schedule": timedelta(seconds=60 * 60),
"args": ()
},
}
- celery.py(固定名称,celery A celery_task beat:会在celery.py文件中查找celery应用)
from __future__ import absolute_import # 保证celery导入不会出错,因为有celery.py文件
from celery import Celery
# 创建celery应用对象
app = Celery("celery_demo")
# 导入celery的配置信息
app.config_from_object("celery_task.celeryconfig")
- t1.py
from redis import StrictRedis
from celery_task.celery import app
@app.task
def test11():
sr = StrictRedis(host='127.0.0.1', port=6379, db=0, decode_responses=True)
sr.set('test11', '12')
- t2.py
from celery_task.celery import app
def test33():
print("test33----------------")
def test44():
print("test44--------------")
test33()
@app.task
def celery_run():
test33()
test44()
if __name__ == '__main__':
celery_run()
- 发布并执行(注意执行的路径)