最完整的 django celery 实现异步、延迟、定时任务

1、首先环境介绍

win10专业版 (感觉不太重要 但是win很重要,其他操作系统可能执行命令有所差别 )
redis 要本地下载并启动起来 打开一个黑窗口运行redis-server这个不要关闭,如下图: 我的redis版本:Redis-x64-5.0.14.1
resp-2022.1.1 这个最好也下载一下吧,其功能类似Navicat,图形化界面操作redis数据库
conda 最好有,没有也无所谓
下面是几个重要的版本最好一致
python版本   Python 3.10.16
下边这些事通过pip 安装的  安装方式可以为 pip install 名字==版本号 -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple
例如: pip install celery ==5.4.0 -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple 
celery            5.4.0
Django            4.2
eventlet          0.38.2   # 貌似Linux不需要安装它
redis             5.2.1  # 此redis是和上边的redis进行连通的
其他包安装如下:(安装完上边的,下边这些应该都会自动安装上)
amqp              5.3.1      
asgiref           3.8.1      
async-timeout     5.0.1      
billiard          4.2.1
celery            5.4.0
click             8.1.7
click-didyoumean  0.3.1
click-plugins     1.1.1
click-repl        0.3.0
colorama          0.4.6
Django            4.2
dnspython         2.7.0
eventlet          0.38.2
greenlet          3.1.1
kombu             5.4.2
pip               24.2
prompt_toolkit    3.0.48
python-dateutil   2.9.0.post0
redis             5.2.1
setuptools        75.1.0
six               1.17.0
sqlparse          0.5.3
typing_extensions 4.12.2
tzdata            2024.2
vine              5.1.0
wcwidth           0.2.13
wheel             0.44.0

redis-server 一直运行起来,界面如下
在这里插入图片描述

2、创建一个django项目

django-admin startproject django_celery
cd django_celery
python  manage.py  startapp  app01

最后的项目结构如下:

在这里插入图片描述

3、异步和延迟任务的配置

django celery 官方配置文档如下:https://docs.celeryq.dev/en/main/django/first-steps-with-django.html#using-celery-with-django

3.1 在启动项目目录下创建一个celery.py 其内容如下:

import os
from celery import Celery

# 1 导入django的配置文件(可以在WSGI中找到)---》后续在celery的任务中,就可以直接使用django的orm,缓存 
# django_celery 为启动app的名字,必须要换成你的
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_celery.settings')
# 2 实例化得到celery对象, myproj 随便起个名字
app = Celery('myproj')
# 3 celery的配置,使用django 配置文件中的配置--》刚刚写的配置
app.config_from_object('django.conf:settings')

# 4 这句话会去所有app中,自动查找 tasks.py 文件,作为任务文件
app.autodiscover_tasks()

# 这样设置在这里也是无效的
# app.conf.timezone = "Asia/Shanghai"
# # 是否使用utc
# app.conf.enable_utc = False

3.2 django_celery/init.py中的内容如下:

from .celery import app as celery_app

__all__ = ('celery_app',)

3.3 setting中的配置如下:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # 要把应用添加上去,要换成你的app(通过python  manage.py  startapp  app01创建的)
    "app01.apps.App01Config",
]

# 在setting文件的最下边添加一下几行内容
############# celery的配置信息######
#1 Broker配置,使用Redis作为消息中间件
BROKER_URL = 'redis://127.0.0.1:6379/1'
#2 BACKEND配置,使用redis
RESULT_BACKEND = 'redis://127.0.0.1:6379/2'
#3 序列化方案--》json
ACCEPT_CONTENT = ['json']
TASK_SERIALIZER = 'json'
# 结果序列化方案
RESULT_SERIALIZER = 'json'

# 4 任务结果过期时间,秒
TASK_RESULT_EXPIRES = 60 * 60 * 24
#5 时区配置
TIMEZONE = 'Asia/Shanghai'
USE_TZ = False

3.4、在app01下创建一个task.py,其内容如下:

import time
from datetime import datetime
from celery import shared_task


# 任务函数 以后你的任务都可以写这里
@shared_task
def add(a, b):
    print("datetime.utcnow()", datetime.utcnow())
    print("datetime.utcnow()", datetime.now())
    time.sleep(2)
    print("11111111111", a, b)
    return a + b

3.5、对django_celery/urls.py这个文件夹中的路径进行修改其内容如下

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path("app01/", include('app01.urls'))
]

3.6、在app01下创建urls.py,其内容如下

from django.urls import path
from app01 import views

urlpatterns = [
    path("asynchronous/", views.asynchronous),
    path("get_delay/", views.get_delay),
]

3.7 app01/views.py中的内容如下:

from datetime import datetime, timedelta

from django.http import JsonResponse
from django.shortcuts import HttpResponse
from app01.task import add


# 异步任务函数
def asynchronous(request):
    mobile = int(request.GET.get('mobile'))
    print(mobile)
    # 通过delay来调用异步方法
    # add这个函数没有被shared_task修饰,那么这里就会报错
    # 虽然是delay但是是异步的而不是延迟的
    res = add.delay(mobile, 5)
    return JsonResponse({'code': 200, 'msg': res.id})


# 延迟任务函数 celery -A django_celery worker  -l info -P eventlet
def get_delay(request):
    mobile = int(request.GET.get('mobile'))
    print(mobile)
    print("datetime.now()", datetime.now())
    eta = datetime.utcnow() + timedelta(seconds=10)  # 使用这个能等10秒后延迟执行
    # eta = datetime.now() + timedelta(seconds=5)  # 使用不行,也就是说现在的时区设置是不对的不符合celery的要求
    # res = add.apply_async(args=[], eta=eta)
    res = add.apply_async(args=[mobile, 5], eta=eta)
    return JsonResponse({'code': 200, 'msg': res.id})

可以发现异步任务和延迟任务的差别其实就在调用函数上

3.8 启动django

python .\manage.py runserver

在这里插入图片描述

3.9 启动celery

celery -A django_celery worker  -l info -P eventlet
# linux和Mac貌似不需要加-P eventlet  另外这个worker顺序不能随便更改,即: 
# celery worker -A django_celery -l info -P eventlet 这样写不对

在这里插入图片描述

3.10 对异步任务的校验: 在浏览器中输入以下内容

http://127.0.0.1:8000/app01/asynchronous/?mobile=1234567890

在这里插入图片描述
任务执行窗口返回的结果如下:
在这里插入图片描述

3.11 对延迟任务的校验 :在浏览器中输入以下内容

http://127.0.0.1:8000/app01/get_delay/?mobile=1234567890

在这里插入图片描述

等待10秒中后会观察到此窗口的变化,即延迟执行

[2024-12-14 16:26:29,073: INFO/MainProcess] Task app01.task.add[dddf93ae-90c9-4a00-b725-a4199789bca1] received
[2024-12-14 16:26:38,979: WARNING/MainProcess] datetime.utcnow()
[2024-12-14 16:26:38,980: WARNING/MainProcess]  
[2024-12-14 16:26:38,980: WARNING/MainProcess] 2024-12-14 08:26:38.979329
[2024-12-14 16:26:38,980: WARNING/MainProcess] datetime.utcnow()
[2024-12-14 16:26:38,980: WARNING/MainProcess]
[2024-12-14 16:26:38,981: WARNING/MainProcess] 2024-12-14 16:26:38.980365
[2024-12-14 16:26:40,988: WARNING/MainProcess] 11111111111
[2024-12-14 16:26:40,988: WARNING/MainProcess]  
[2024-12-14 16:26:40,988: WARNING/MainProcess] 1234567890
[2024-12-14 16:26:40,988: WARNING/MainProcess]
[2024-12-14 16:26:40,988: WARNING/MainProcess] 5
[2024-12-14 16:26:40,992: INFO/MainProcess] Task app01.task.add[dddf93ae-90c9-4a00-b725-a4199789bca1] succeeded in 2.0s: 1234567895 

4、定时任务的设置

4.1、在django_celery/settings.py中的最后再添加如下内容:

#  定时任务的设置
from datetime import timedelta
CELERYBEAT_SCHEDULE = {
    # every_5_second 一个名字,随便起个即可
    'every_5_second': {
        'task': 'app01.task.add',  # app01.task.add 定位到定时的方法
        # 设置每隔5s执行一次add任务
        'schedule': timedelta(seconds=5),
        'args': (33, 44),  # add方法需要的参数
    }
}

4.2、开启定时任务

celery -A django_celery beat  -l info

在这里插入图片描述

4.3、定时结果验证 每个5秒执行一次

在这里插入图片描述

至此结束,完整的setting内容如下:

"""
Django settings for django_celery project.

Generated by 'django-admin startproject' using Django 4.2.

For more information on this file, see
https://docs.djangoproject.com/en/4.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.2/ref/settings/
"""

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-li#2-^ajl^6(%xcr$+3ib4tr3!z2n=kwyre8u_=3kpb$480hdn'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    "app01.apps.App01Config",
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'django_celery.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'django_celery.wsgi.application'


# Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}


# Password validation
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/4.2/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/

STATIC_URL = 'static/'

# Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'


############# celery的配置信息######
#1 Broker配置,使用Redis作为消息中间件
BROKER_URL = 'redis://127.0.0.1:6379/1'
#2 BACKEND配置,使用redis
RESULT_BACKEND = 'redis://127.0.0.1:6379/2'
#3 序列化方案--》json
ACCEPT_CONTENT = ['json']
TASK_SERIALIZER = 'json'
# 结果序列化方案
RESULT_SERIALIZER = 'json'

# 4 任务结果过期时间,秒
TASK_RESULT_EXPIRES = 60 * 60 * 24
#5 时区配置
TIMEZONE = 'Asia/Shanghai'
USE_TZ = False
# ENABLE_UTC = False

#  定时任务的设置
from datetime import timedelta
CELERYBEAT_SCHEDULE = {
    # every_5_second 一个名字,随便起个即可
    'every_5_second': {
        'task': 'app01.task.add',  # app01.task.add 定位到定时的方法
        # 设置每隔5s执行一次add任务
        'schedule': timedelta(seconds=5),
        'args': (33, 44),  # add方法需要的参数
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值