一.基本信息

1.简介
Celery是一个分布式消息队列,通常用来执行某些耗时操作和定时任务,支持异步任务调度。Celery 不仅可以单机运行,也能够同时在多台机器上运行,甚至可以跨数据中心。

2.组成

  1. 任务队列
    客户端将要执行任务的消息放入任务队列,执行节点worker进程持续监控队列,有新任务时就取出来执行,即生产者-消费者模型,客户端作为生产者,执行节点worker作为消费者,它们之间通过任务队列进行传递;
  2. borker
    消息中间件,负责接受任务生产者发送过来的任务处理消息,存进队列之后再进行调度,分发给任务消费方 (celery worker),常用工具为redis和RabbitMQ等;
  3. worker
    执行单元,任务队列的消费者,持续监控任务队列,当有新的任务时取出来执行;
  4. backend
    任务结果存储,用来存储worker执行任务的结果,Celery支持以不同方式存储任务的结果,包括Redis,MongoDB,Django ORM,AMQP等
  5. 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

  1. 开启BEAT
    celery beat -A celery_project -l INFO
  2. 开启worker
    celery -A celery_project worker -l INFO -P eventlet
  3. 同时开启
    celery -B -A celery_project worker -l INFO (windows上好像不支持)

示例参考:https://www.imooc.com/learn/1051