celery-分布任务神器--django任务

本文介绍了Celery作为一个分布式异步框架在处理大量邮件发送或博客订阅推送等场景下的应用。Celery涉及的基本概念包括Broker(如RabbitMQ、Redis)和Backend(如数据库)。推荐使用RabbitMQ作为Broker,MySQL作为Backend。文章详细阐述了Celery的架构,包括消息中间件、任务执行单元和任务结果存储,并提供了安装、编写、启动、测试和项目模式的步骤,还提及了Celery的定时任务和配置文件定义任务的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

celery是一个分布式异步框架,当我们有一个需求,比如我需要进行大批量的邮箱发送,或者博客订阅推送的时候,会造成大量的等待执行,这时候就会用到celery,

Celery 介绍

 

在Celery中几个基本的概念,需要先了解下,不然不知道为什么要安装下面的东西。概念:Broker、Backend。

什么是broker?

broker是一个消息传输的中间件,可以理解为一个邮箱。每当应用程序调用celery的异步任务的时候,会向broker传递消息,而后celery的worker将会取到消息,进行对于的程序执行。好吧,这个邮箱可以看成是一个消息队列。其中Broker的中文意思是 经纪人 ,其实就是一开始说的 消息队列 ,用来发送和接受消息。这个Broker有几个方案可供选择:RabbitMQ (消息队列),Redis(缓存数据库),数据库(不推荐),等等

什么是backend?

通常程序发送的消息,发完就完了,可能都不知道对方时候接受了。为此,celery实现了一个backend,用于存储这些消息以及celery执行的一些消息和结果。Backend是在Celery的配置中的一个配置项 CELERY_RESULT_BACKEND ,作用是保存结果和状态,如果你需要跟踪任务的状态,那么需要设置这一项,可以是Database backend,也可以是Cache backend,具体可以参考这里: CELERY_RESULT_BACKEND 。

对于 brokers,官方推荐是 rabbitmq 和 redis,至于 backend,就是数据库。为了简单可以都使用 redis。

我自己演示使用RabbitMQ作为Broker,用MySQL作为backend。

来一张图,这是在网上最多的一张Celery的图了,确实描述的非常好

这里写图片描述

Celery的架构由三部分组成,消息中间件(message broker),任务执行单元(worker)和任务执行结果存储(task result store)组成。

消息中间件

Celery本身不提供消息服务,但是可以方便的和第三方提供的消息中间件集成。包括,RabbitMQ, RedisMongoDB (experimental), Amazon SQS (experimental),CouchDB (experimental), SQLAlchemy (experimental),Django ORM (experimental), IronMQ

任务执行单元

Worker是Celery提供的任务执行的单元,worker并发的运行在分布式的系统节点中。

任务结果存储

Task result store用来存储Worker执行的任务的结果,Celery支持以不同方式存储任务的结果,包括AMQP, redis,memcached, mongodb,SQLAlchemy, Django ORM,Apache Cassandra, IronCache 等。

一、安装

pip install celery redis 

二、编写

#tasks.py

from celery import Celery
import time

app = Celery("task_transport", #任务名称,可随意填写
            borker="redis://127.0.0.1:6379", #任务队列,指定从哪里调度,
            backend="redis://127.0.0.1:6379" #存放结果
        )

@app.task
def add(x,y):
    time.sleep(15)
    print('function is running')
    return x + y

三、启动

celery  -A task worker -l info #task为脚本名称 worker为工作模式,info输出日志到屏幕

四、测试

#终端ipython
In [1]: import celery

In [2]: import task

In [3]: s = task.add.delay(10,20) #调用add函数的delay方法传入参数

In [4]: s
Out[4]: <AsyncResult: c3e9c1d3-310f-46cf-9956-b3b897f10b7b>

In [5]: s.get() #获取返回结果

五、项目模式

#celery_project/
    task2.py    
    celery.py   
    _pycache__ 

#celery.py

from __future__ import absolute_import,unicode_literals 
from celery import Celery 

app = Celery(
        "project",
        broker="redis://127.0.0.1:6379",
        backend="redis://127.0.0.1:6379",
        include=["task1","task2"]) #执行多个任务,这里对应的是当前目录的task1.py,task2.py

app.conf.update(
    result_expires=3600, #任务结果一小时内没有获取则过期
)
app.config_from_object('celery_app.celeryconfig') #通过Celery实例加载配置模块

if __name__ == '__main__':
    app.start()

#task1.py & task2.py

from __future__ import absolute_import,unicode_literals 
from .celery import app 

@app.task
def add(x,y):
    return x + y 

@app.task
def delete(x,y):
    return x - y 

#执行
celery -A celery_project worker -l info //celery_project为目录名称

#测试方法一样,开启另外一个终端调用task1或task2.py中的函数

celery常用方法

result = task.add.delay(10,20)  //调用函数和delay方法

result.get() //获取结果,timeout默认为0

result.ready() //如果函数执行出现阻塞则返回False,可进行判断!

result.get(propagate=False) // 如果出错,获取错误结果,不触发异常

result.traceback //打印异常详细结果

result.id //任务id

celery multi start name  project_name -l info //启动celery任务并后台运行

celery multi restart worker -A  celery_project //重新启动celery任务

celery multi stop worker //停止

Celery定时任务

#task1.py

from __future__ import absolute_import,unicode_literals
from .celery import app //从主程序倒入
from celery.schedules import crontab

@app.on_after_configure.connect
def setup_periodic_tasks(sender,**kwargs):

    #请注意,这里的name不能相同!必须唯一,否则执行该方法!
    sender.add_periodic_task(5.0,delete.s(10,20),name="add every 10") //每五秒
    sender.add_periodic_task(5.0,add.s(2,20),name="add every 10")

    sender.add_periodic_task(
            crontab(hour=20,minute=15), //每天20点15
            add.s(200,5)
        )

@app.task
def add(x,y):
    return x + y

@app.task
def delete(x,y):
    return x - y 

#启动worker
celery -A celery_project worker -l debug 

#启动beat
celery -A celery_project.task1 beat -l debug 

基于配置文件方式定义执行任务

app.conf.beat_schedule = {
    'add-every-30-seconds' : {
        'task': 'celery_project.task1.add',
        'schedule': 5.0,
        'args': (100,200)
    }
}

app.conf.timezone = 'UTC'

Django & Celery

pip install django-celery  //安装django-celery

#需要和settings.py同级创建celery.py
#settings.py
INSTALL_APP -> djcelery //INSTALL_APP下加入djcelery

import djcelery

djcelery.setup_loader()

BROKER_URL = 'redis://127.0.0.1:6379' #队列地址

CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379' #存储结果

CELERY_TASK_SERIALIZER = 'json'

CELERY_RESULT_SERIALIZER = 'json'

CELERY_ACCEPT_CONTENT = ['json']

CELERY_IMPORTS = ('api.tasks', )

CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler' #是使用了django-celery默认的数据库调度模型,任务执行周期都被存在你指定的orm数据库中

CELERYD_CONCURRENCY = 20 #worker并发数

CELERY_TASK_RESULT_EXPIRES = 1200 #任务结果过期时间

CELERYD_PREFETCH_MULTIPLIER = 4 # celery worker 每次去redis取任务的数量

CELERYD_MAX_TASKS_PER_CHILD = 200 # 每个worker执行了多少任务就会死掉,我建议数量可以大一些,比如200

#celery.py -> 与settings.py同级

from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
from django.conf import settings

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Celery_Project.settings') 

app = Celery('Celery_Project')

app.config_from_object('django.conf:settings')

app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

#__init__.py

from __future__ import absolute_import, unicode_literals
from .celery import app as celery_app

#{app_name}/tasks.py 可以在每一个app下创建tasks.py文件进行celery任务编写

from __future__ import absolute_import, unicode_literals
from celery import shared_task

@shared_task
def add(x, y):
    return x + y

#start
python manage.py migrate djcelery //生成数据表

python manage.py runserver  //启动django

python manage.py  celery worker -c 6 -l debug //启动celery
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值