【Celery】Django项目celery异步的使用

原文作者:我辈李想
版权声明:文章原创,转载时请务必加上原文超链接、作者信息和本声明。


文章目录

  • 前言
  • 一、安装 Celery
  • 二、消息队列(Broker)
  • 三、Django配置celery
    • 1.创建celery_config.py文件
    • 2.创建mycelery.py文件
    • 3.修改__init__.py文件
    • 4.settings文件添加配置
    • 4.编写自己的task任务
    • 5.celery调用
    • 6、celery重试
      • 方式一:shared_task中重试
      • 方式二:app.task装饰器设置重试
      • 方式三:Task继承
    • 7.日志
  • 四、celery启动和停止(Worker)
    • 1.windows启动celery
    • 2.linux启动celery
    • 3.停止
  • 五、celery监控
    • 1.Flower监控
    • 2.django-celery-result监控


前言

Django 是一个基于 Python 的 Web 开发框架,而 Celery 是一个 Python 实现的异步任务队列(Task Queue),它能够处理大规模的分布式任务,用于实现 Django 中的异步任务。

使用 Celery 和 Django 可以实现以下功能:

  1. 异步任务处理:Celery 可以将耗时的任务异步处理,加速 Web 应用的响应速度。

  2. 定时任务:Celery 可以通过设置定时任务,定期执行某些任务,例如定时清理数据库。

  3. 异常处理:Celery 可以在任务执行失败时捕获异常,并进行相应的处理,例如发送邮件通知管理员。

  4. 分布式任务:Celery 可以将任务分发到多个节点进行处理,提高任务执行效率和并发性。

在 Django 中使用 Celery,需要进行以下几个步骤:

  1. 安装 Celery 和消息队列(例如 RabbitMQ、Redis 等)。

  2. 在 Django 中配置 Celery。

  3. 定义任务函数,并使用 Celery 的装饰器进行装饰。

  4. 在 Django 视图函数中调用任务函数,并将任务加入 Celery 队列执行。

  5. 监控 Celery 任务执行状态和日志。


一、安装 Celery

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple celery==5.3.1

二、消息队列(Broker)

celery支持的消息队列常用的是RabbitMQ、Redis 等。这里就以Redis为例进行说明。

Redis的安装和使用

三、Django配置celery

1.创建celery_config.py文件

在django的settings.py同级目录添加celery_config.py

# -*- coding: utf-8 -*-
"""
@author:lpf
@file: celery_config.py
@time: 2023/8/7  17:17
"""
# 启用 UTC 时区
import os
from datetime import timedelta

# 时区,与django的TIMEZONE一致
CELERY_TIMEZONE = "Asia/Shanghai"

CELERY_TASK_TRACK_STARTED = True

# 有些情况防止死锁
CELERYD_FORCE_EXECV = True
# 任务失败允许重试
CELERY_ACKS_LATE = True
# Worker并发数量,一般默认CPU核数,可以不设置
CELERY_WORKER_CONCURRENCY = 2  # CELERYD_CONCURRENCY = 4
# 每个worker最多执行的任务数,超过这个就将worker进行销毁,防止内存泄漏,默认无限
CELERYD_MAX_TASKS_PER_CHILD = 100
# 单个任务运行的最大时间,超过这个时间,task就会被kill
CELERY_TASK_TIME_LIMIT = 30 * 60
# 过期时间,默认一天
CELERY_RESULT_EXPIRES = 30 * 60
# 任务限流
# CELERY_TASK_ANNOTATIONS = {'tasks.add': {'rate_limit': '10/s'}}

# celery 内容等消息的格式设置,默认json
if os.name != "nt":
    # Mac and Centos
    # worker 启动命令:celery -A 项目名 worker -l info
    CELERY_ACCEPT_CONTENT = ['application/json', ]
    CELERY_TASK_SERIALIZER = 'json'
    CELERY_RESULT_SERIALIZER = 'json'
else:
    # windows
    # pip install eventlet
    # worker 启动命令:celery -A 项目 worker -l info -P eventlet
    CELERY_ACCEPT_CONTENT = ['pickle', ]
    CELERY_TASK_SERIALIZER = 'pickle'
    CELERY_RESULT_SERIALIZER = 'pickle'

# 定义任务模块的名称,需要在 Django 项目中创建 tasks.py 文件(与下一步的app配置设置一个即可)
# CELERY_IMPORTS = ('commodity.tasks',)

# 队列
CELERY_QUEUES = {
    # 定时任务队列
    'beat_tasks': {
        'exchange': 'beat_tasks',
        'exchange_type': 'direct',
        'binding_key': 'beat_tasks'
    },
    # 普通任务队列
    'work_tasks': {
        'exchange': 'work_tasks',
        'exchange_type': 'direct',
        'binding_key': 'work_tasks'
    }
}
# 设置默认的队列
CELERY_DEFAULT_QUEUE = 'work_tasks'
# 定时任务
CELERYBEAT_SCHEDULE = {
    'task1': {
        'task': 'upload-task',  # 指定任务名称
        'schedule': timedelta(seconds=5),  # 任务执行时间,每5秒执行一次
        'options': {
            'queue': 'beat_tasks' # 指定队列
        }
    }
}

celery的其他参数请自行查阅celery官网

2.创建mycelery.py文件

# -*- coding: utf-8 -*-
"""
@author:lpf
@file: celery.py
@time: 2023/7/27  17:22
"""
import os

from celery import Celery

# 设置django环境变量
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tianyiapi.settings') # 项目配置

# 创建celery实例化对象
app = Celery('tianyiapi')   # 项目名

# 启动项目celery配置
app.config_from_object('django.conf:settings', namespace='CELERY')

# 自动发现项目中的tasks
app.autodiscover_tasks()

3.修改__init__.py文件

from .mycelery import app as celery_app

__all__ = ('celery_app',)

4.settings文件添加配置

# 配置 Celery
from .mycelery import *

# 指定 Broker 使用 Redis,Broker 负责任务的分发和调度
CELERY_BROKER_URL = 'redis://127.0.0.1:6379/1'
# 指定结果存储 Backend 使用 Redis,Backend 负责存储任务执行结果
CELERY_RESULT_BACKEND = 'redis://localhost:6379/1'
# django-celery-results 设置
CELERY_RESULT_BACKEND = 'django-db'

4.编写自己的task任务

django项目都是有很多app的(通过startapp命令创建),我们需要在app文件下新建tasks.py文件

from celery import shared_task

@shared_task
def send_email(to, subject, message):
    # 发送邮件代码

5.celery调用

celery调用主要有delay和apply_async两种方式,其中delay可设置参数较少,apply_async可以设置延时、过期等。

# delay方法+参数
task_name.delay(args1, args2, kwargs=value_1, kwargs2=value_2)# apply_async+参数
task.apply_async(args=[arg1, arg2], kwargs={key:value, key:value})

# apply_async+设置
add.apply_async((1, 2), queue='lopri', countdown=60, expires=120,ignore_result=True)  # 使用lopri队列,距现在60秒后开始执行,两分钟后过期,忽略结果

示例:

from django.shortcuts import render
from .tasks import send_email

def contact(request):
    # 处理表单提交

    # 将任务加入队列
    send_email.delay(to, subject, message)

    return render(request, 'contact.html', {'success': True})

4和5使用 @shared_task 装饰器定义了一个 send_email 异步任务,然后在 Django 视图函数中调用该任务,并使用 delay() 方法将任务加入 Celery 队列执行。

注意,在使用 Celery 进行异步任务处理时,需要注意任务的并发性和任务的执行结果。为了提高任务的并发性,可以将任务分发到多个节点进行执行;为了获取任务的执行结果,可以使用 Celery 提供的结果存储和状态监控功能。

6、celery重试

我们在使用celery时,可能因为各种原因存在问题,导致程序没有按照我们制定的方式运行,对于有些任务,我们就需要继续执行。Celery提供了一些方法来处理任务失败和重试,可以在任务失败时自动重试或手动重试。

方式一:shared_task中重试

from celery import shared_task

@shared_task
def my_task(*args, **kwargs):
    try:
        # 执行任务
    except Exception as exc:
        # 引发重试
        raise my_task.retry(exc=exc, countdown=60, max_retries=10)
 

在上述代码中,当任务执行发生异常时,会引发一个重试,参数说明如下:

exc:异常对象,用于调试错误;
countdown:重试之前的倒计时,以秒为单位;
max_retries:重试的最大次数。

以上例子中,每次重试之间的间隔为60秒,最多重试10次。

方式二:app.task装饰器设置重试

在定义任务时,可以设置一些参数来实现自动重试。例如:

@app.task(bind=True, max_retries=3, default_retry_delay=10)
def my_task(self, *args, **kwargs):
    try:
        # 执行任务
    except Exception as exc:
        raise self.retry(exc=exc)

这个任务被设置为最大重试3次,每次重试间隔10秒钟。如果任务执行时出现异常,会自动引发重试任务。

方式三:Task继承

这种方式没怎么用过,需要的可以好好研究。

class MyTask(Task):
    def run(self, *args, **kwargs):
        try:
            # 执行任务
        except Exception as exc:
            raise self.retry(exc=exc, countdown=60, max_retries=10)

my_task = MyTask.bind(app)

@app.task(base=MyTask,bind=True)

这个自定义任务类可以手动引发重试,设置最大重试次数和计数器。

需要注意的是,自动重试和手动重试都可能导致无限循环重试的问题。在处理任务失败和重试时,一定要谨慎处理。

7.日志

from celery.utils.log import get_task_logger

logger = get_task_logger(__name__)

@app.task
def add(x, y):
    logger.info('Adding {0} + {1}'.format(x, y))
    return x + y

四、celery启动和停止(Worker)

1.windows启动celery

在命令行中进入Python脚本所在的目录,然后执行以下命令启动Celery worker:

celery -A tasks worker --loglevel=info

这里的-A参数表示要加载的Celery应用模块,worker表示启动worker进程,--loglevel表示日志级别。

2.linux启动celery

3.停止

celery multi stop w1 -A proj -l info
# linux
ps auxww | grep 'celery worker' | awk '{print $2}' | xargs kill -9

五、celery监控

1.Flower监控

  1. 安装

     pip install -i https://pypi.tuna.tsinghua.edu.cn/simple flower
    
  2. 启动

     celery flower -A  项目名 --address=127.0.0.1 --port=5555
    

2.django-celery-result监控

文档地址

你可能感兴趣的:(Python开始入门,django,python,后端)