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方法需要的参数
}
}