Django使用celery小记

基础环境

python 3.7
amqp 2.6.0
celery 4.4.3
Django 2.2
flower 0.9.4
可选使用djcelery,这里我使用的原生celery

celery简介及应用场景

Celery是基于Python开发的一个分布式任务队列框架,采用生产者-消费者模式,主要由三部分组成:broker(消息队列)、workers(消费者:处理任务)、backend(存储结果)
主要应用场景:
1、异步任务(async task) 针对请求执行的任务时间较长的情况
2、定时任务(crontab)

1.用户发起请求接口
2.接口将任务发送到broker队列
3.celery worker 监控 broker队列任务并处理
4.celery worker 将结果存储到backend
在这里插入图片描述
从图上可以看出Celery包含几个模块:

任务模块 Task (生产者)
包括异步任务和定时任务,异步任务通常在业务逻辑中被触发并发送到任务队列中,而定时任务是由Celery Beat进程周期性的将任务发往任务队列。

消息中间件 Broker (中间人)
Broker就是任务调度队列,接受任务生产者发送来的消息,将任务存入队列,之所以需要中间人的原因是Celrey本身是不提供消息队列的服务,所以需要第三方组件实现,常用的有RabbitMQ、Redis。

任务执行单元Worker (消费者)
Worker是执行任务的单元,它实时监控消息队列,如果有任务就获取任务并执行它。

任务存储Backend(存储结果)
Backend用于存储任务的执行结果,存储可以使用RabbitMQ或者Redis或者数据库等。

异步任务

目录结构
mysite/mysite是项目配置
mysite/ola_utils是新建的app

mysite
├── README.MD
├── db.sqlite3
├── manage.py
├── mysite
│   ├── __init__.py
│   ├── __pycache__
│   ├── celery.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── ola_utils
    ├── __init__.py
    ├── __pycache__
    ├── admin.py
    ├── apps.py
    ├── migrations
    ├── models.py
    ├── tasks.py
    ├── tests.py
    └── views.py

celery主配置文件

'''
mysite/mysite/celery.py
'''
# -*- coding: utf-8 -*-
# @Time    : 2020/6/8 5:03 PM
# @Author  : zhangzd
# @Email   : [email protected]
# @File    : celery.py
# @Software: PyCharm
from __future__ import absolute_import, unicode_literals

import os

from celery import Celery, platforms

# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')

app = Celery('mysite', backend='amqp', broker='amqp://guest:guest@localhost:5672')

# Using a string here means the worker doesn't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
#   should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings', namespace='CELERY')

# Load task modules from all registered Django app configs.
app.autodiscover_tasks()


# 允许root 用户运行celery
platforms.C_FORCE_ROOT = True

# 防止内存泄漏,限制worker执行任务次数
app.conf.worker_max_tasks_per_child = 40

@app.task(bind=True)
def debug_task(self):
    print('Request: {0!r}'.format(self.request))

# 定时任务
from celery.schedules import crontab

app.conf.update(
    CELERYBEAT_SCHEDULE={
        'send-report': {
            # 具体需要执行的函数
            # 该函数必须要使用@shared_task装饰
            'task': 'ola_utils.tasks.report',
            # 定时时间
            # 每分钟执行一次,不能为小数
            'schedule': crontab(minute='*/1'),
            # 或者这么写,每小时执行一次
            # "schedule": crontab(minute=0, hour="*/1")
            # 执行的函数需要的参数
            'args': ()
        }
    }
)

在mysite/init.py文件中增加如下内容,确保django启动的时候这个app能够被加载到

'''
mysite/mysite/__init__.py
'''

from __future__ import absolute_import, unicode_literals

# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
from .celery import app as celery_app

__all__ = ('celery_app',)

注意tasks.py必须建在各app的根目录下,且只能叫tasks.py,不能随意命名

'''
mysite/ola_utils/tasks.py
'''
from __future__ import absolute_import, unicode_literals

from celery import shared_task

import time



@shared_task
def add(x, y):
    time.sleep(10)
    return x + y

在视图文件内调用视图函数触发异步任务

'''
mysite/ola_utils/views.py
'''
from django.shortcuts import render

# Create your views here.
import time
from django.http import HttpResponse

from ola_utils.tasks import add

def heartbeat(request):
    t = time.time()
    try:
        # r = test.delay()
        r = add.delay(2,6)
        print(r)
    except Exception as e:
        print(e)
    return HttpResponse(t)

启动celery worker
celery -A mysite worker -l info

定时任务

# 定时任务配置
from celery.schedules import crontab

app.conf.update(
    CELERYBEAT_SCHEDULE={
        'send-report': {
            # 具体需要执行的函数
            # 该函数必须要使用@shared_task装饰
            'task': 'ola_utils.tasks.report',
            # 定时时间
            # 每分钟执行一次,不能为小数
            'schedule': crontab(minute='*/1'),
            # 或者这么写,每小时执行一次
            # "schedule": crontab(minute=0, hour="*/1")
            # 执行的函数需要的参数
            'args': ()
        }
    }
)
'''
mysite/ola_utils/tasks.py
'''

@shared_task
def report():
    print(5)
    return 5

同时执行异步任务和定时任务
celery -B -A mysite worker -l info

结果
在这里插入图片描述

其他

celery 官网:https://docs.celeryproject.org/en/4.4.3/django/first-steps-with-django.html
celery 配置参数
https://docs.celeryproject.org/en/master/userguide/configuration.html?highlight=CELERYD_MAX_TASKS_PER_CHILD#std:setting-worker_max_tasks_per_child

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章