一.基本信息
1.简介
Celery是一个分布式消息队列,通常用来执行某些耗时操作和定时任务,支持异步任务调度。Celery 不仅可以单机运行,也能够同时在多台机器上运行,甚至可以跨数据中心。
2.组成
- 任务队列
客户端将要执行任务的消息放入任务队列,执行节点worker进程持续监控队列,有新任务时就取出来执行,即生产者-消费者模型,客户端作为生产者,执行节点worker作为消费者,它们之间通过任务队列进行传递; - borker
消息中间件,负责接受任务生产者发送过来的任务处理消息,存进队列之后再进行调度,分发给任务消费方 (celery worker),常用工具为redis和RabbitMQ等; - worker
执行单元,任务队列的消费者,持续监控任务队列,当有新的任务时取出来执行; - backend
任务结果存储,用来存储worker执行任务的结果,Celery支持以不同方式存储任务的结果,包括Redis,MongoDB,Django ORM,AMQP等 - beat
Celery beat 是一个任务调度器,它以独立进程的形式存在。
Celery beat 进程会读取配置文件的内容,周期性地将配置中到期需要执行的 任务发送给任务队列(定时任务)。
Celery beat 是 Celery系统自带的任务生产者。 在一个 Celery 系统中,只能存在一个Celery beat调度器。
二.简单示例
1.创建celery程序
from celery import Celery
borker = "redis://127.0.0.1:6379/1"
backend = "redis://127.0.0.1:6379/2"
# 创建一个Celery实例
app = Celery("my_task", broker=borker, backend=backend)
# 通过装饰器创建一个任务函数
@app.task
def add(x, y):
print("进入函数")
time.sleep(4)
return x + y
2.启动任务执行单元worker
celery -A celery_task worker -l INFO
- -A celery_task 表示程序的模块名称(对应celery_task.py文件);
- worker:表示启动一个执行单元;
- -l 表示打印日志的级别
win10启动报错:ValueError: not enough values to unpack (expected 3, got 0)
解决方案(参考:) 安装第三方库:pip install eventlet
启动命令改为:celery -A celery_task worker -l INFO -P eventlet
3.编写程序调用任务函数
from celery_task import add
if __name__ == "__main__":
print("开始执行函数...")
# delay方法异步调用
result = add.delay(3, 6)
print("函数执行结束...")
print(result) # 打印结果为taskid:9e5eea50-26fc-4a67-8438-a5bdd351b4e3
# result.ready() 判断任务是否执行完毕
# result.get() 获取任务的返回结果
# result.successful() 判断任务是否成功执行
三.celery项目
1.项目结构
celery_project
│ __init__.py
│ app.py
│ settings.py
│ task1.py
│ task2.py
2. app.py worker的入口
from celery import Celery
app = Celery("demo")
# 通过celery实例,加载配置模块
app.config_from_object("celery_project.settings")
3. settings.py 配置文件
BROKER_URL = "redis://127.0.0.1:6379/1"
CELERY_RESULT_BACKEND = "redis://127.0.0.1:6379/2"
# 设置时区,默认是UTC
CELERY_TIMEZONE = "Asia/Shanghai"
# 指定任务模块
CELERY_IMPORTS = (
'celery_project.task1',
'celery_project.task2',
)
# 处理结果的展示格式
CELERY_RESULT_SERIALIZER = 'json'
# 任务过期时间
CELERY_TASK_RESULT_EXPIRES = 60 * 60 * 24
4. task1.py 需要执行的任务函数
import time
from celery_project.app import app
@app.task
def add(x, y):
time.sleep(4)
return x+y
5.启动worker
在项目目录外执行
celery -A celery_project.app worker -l INFO -P eventlet
6.执行函数调用
项目目录外创建run.py
from celery_project import task1, task2
print("开始执行")
task1.add.delay(3,6)
task2.multiply.delay(2,7)
print("执行结束")
四.定时任务
基于上个项目内容
1. settings.py 中增加定时任务配置
from datetime import timedelta
from celery.schedules import crontab
# 开启BEAT:celery beat -A celery_project -l INFO
# 开启worker: celery -A celery_project worker -l INFO -P eventlet
# 同时开启:celery -B -A celery_project worker -l INFO (windows上好像不支持)
CELERYBEAT_SCHEDULE = {
"task1": {
"task": "celery_project.task1.add",
"schedule": timedelta(seconds=10), # 每10秒执行一次
"args": (2,6),
},
"task2": {
"task": "celery_project.task2.multiply",
"schedule": crontab(hour=17, minute=40), # 每天的17:40执行
"args": (3, 6),
}
}
2.在两个cmd中启动beat和worker
- 开启BEAT
celery beat -A celery_project -l INFO - 开启worker
celery -A celery_project worker -l INFO -P eventlet - 同时开启
celery -B -A celery_project worker -l INFO (windows上好像不支持)
示例参考:https://www.imooc.com/learn/1051