Django中使用Celery和APScheduler实现定时任务

在之前的文章我们已经学习了Celery和APScheduler的基本使用,下面让我们来了解一下如何在Django中使用Celery和APScheduler

Celery

1.前提工作

python 3.7
pip install celery
pip install eventlet
#5.0版本以下
pip install importlib-metadata==4.8.3(python3.7下可能会出现报错)

2.项目结构

3.异步任务

#tasks.py
from ..main import celery_app
# 装饰器将send_sms_code装饰为异步任务,并设置别名
@celery_app.task(name='send_sms_code')
def send_sms_code(mobile, sms_code):
    print("向手机号{}发送验证码{}".format(mobile,sms_code))
# config.py
broker_url = "redis://127.0.0.1:6379/7"
#main.py
# celery启动⽂件
from celery import Celery
import os

#配置环境
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoProject7.settings')
# 创建celery实例
celery_app = Celery('test')
# 加载celery配置
celery_app.config_from_object('celery_tasks.config')
# ⾃动注册celery任务
celery_app.autodiscover_tasks(['celery_tasks.sms'])

命令启动:

与manage.py平级,执行命令celery -A celery_tasks.main  worker -l info -P eventlet

编写视图函数和路由:

#views.py
from django.shortcuts import render,HttpResponse
from celery_tasks.sms import tasks
# Create your views here.
def index(request):
    tasks.send_sms_code("13417361123","123456")
    return HttpResponse("111")

#urls.py
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/',views.index)
]

 启动项目,然后访问视图即可

4.定时任务

代码只需要改config.py即可:

# config.py
broker_url = "redis://127.0.0.1:6379/7"
from celery_tasks.main import celery_app
from celery.schedules import crontab

#设置定时任务
from datetime import timedelta

# 设置定时任务
celery_app.conf.beat_schedule = {
    "test_task": {
        "task": "send_sms_code",
        # "schedule": crontab(hour=11, minute=28),# 每天的11点28分执行一次任务
        "schedule": timedelta(seconds=1),  # 每秒执行一次任务
        "args": ("13417366781","1111"),  # 这里是传递给任务的参数,元组形式
    }
}

然后在终端启动分别执行两条命令(开两个终端执行):

celery --app=celery_tasks.main worker -P eventlet -l INFO
celery -A celery_tasks.main beat

APScheduler

1.前提工作

pip install django-apscheduler

 2.配置

在settings.py中加入

INSTALLED_APPS = (
    # ...
    "django_apscheduler",
)

apscheduler存在数据库依赖,所以得配置一下数据库信息:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'test',
        'USER': 'root',
        'PASSWORD': '547710',
        'HOST': 'localhost',
        'PORT': '3306'
    }
}

然后运行python manage.py migrate,接着会在数据库中生成两张表:

django_apscheduler_djangojob 表保存注册的任务以及下次执行的时间

django_apscheduler_djangojobexecution 保存每次任务执行的时间和结果和任务状态

3.使用

#views.py
from django_apscheduler.jobstores import DjangoJobStore, register_job

from apscheduler.schedulers.blocking import BlockingScheduler
from datetime import datetime

scheduler = BlockingScheduler()  # 创建调度器
scheduler.add_jobstore(DjangoJobStore(), "default")

#添加定时任务方式一
@register_job(scheduler, "interval", seconds=5, id="func", replace_existing=True, misfire_grace_time=120)
def job():
    print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))

# 添加定时任务方式二
def job1():
    print(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
scheduler.add_job(
        job1,
        'interval',
        seconds=5,
        id='my_job',  # 任务的唯一标识
        replace_existing=True,
)

scheduler.start()

 4.启动

在终端运行python manage.py runserver,效果如下

数据库表记录(有时间差8小时,这个去配置时区即可): 

django_apscheduler_djangojob

django_apscheduler_djangojobexecution  

  • 17
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Django 使用 Apscheduler 实现定时任务时,服务重启后定时任务会失效的原因是因为 Apscheduler 的默认存储方式是内存存储,当服务重启后,内存的数据会被清空,导致定时任务信息丢失。 为了解决这个问题,可以将 Apscheduler 的存储方式改为数据库存储。具体实现步骤如下: 1. 首先安装 ApschedulerDjango 的数据库驱动,比如 psycopg2 或者 mysqlclient。 2. 在 Django 项目的 settings.py 文件配置数据库信息: ``` DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'your_db_name', 'USER': 'your_db_user', 'PASSWORD': 'your_db_password', 'HOST': 'localhost', 'PORT': '5432', } } ``` 3. 在 Django 项目的 settings.py 文件添加 Apscheduler 的配置信息: ``` SCHEDULER_JOBSTORES = { 'default': SQLAlchemyJobStore(url='postgresql://your_db_user:your_db_password@localhost/your_db_name') } SCHEDULER_EXECUTORS = { 'default': {'type': 'threadpool', 'max_workers': 20} } SCHEDULER_JOB_DEFAULTS = { 'coalesce': False, 'max_instances': 3 } SCHEDULER_API_ENABLED = True ``` 其,`url` 参数的格式为:`<database>://<user>:<password>@<host>/<database_name>`,根据自己的数据库信息进行修改。 4. 在 Django 项目的 urls.py 文件注册 Apscheduler 的 API: ``` from apscheduler.scheduler import Scheduler from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore from django_apscheduler.jobstores import DjangoJobStore from django_apscheduler import util scheduler = Scheduler( jobstores={ 'default': DjangoJobStore(), 'sqlalchemy': SQLAlchemyJobStore(url='postgresql://your_db_user:your_db_password@localhost/your_db_name') }, executors={ 'default': {'type': 'threadpool', 'max_workers': 20} }, job_defaults={ 'coalesce': False, 'max_instances': 3 }, timezone=util.get_timezone('Asia/Shanghai') ) # 添加定时任务 def test_job(): print("test job") scheduler.add_job(test_job, 'interval', seconds=10) # 启动定时任务 scheduler.start() # 注册 API from django.urls import path from django_apscheduler.views import DjangoJobView, DjangoJobAllView, DjangoJobRunView urlpatterns = [ path('admin/', admin.site.urls), path('jobs/', DjangoJobView.as_view()), path('jobs/all/', DjangoJobAllView.as_view()), path('jobs/run/<job_id>/', DjangoJobRunView.as_view()), ] ``` 其,`scheduler.add_job()` 函数用于添加定时任务,这里添加了一个每隔 10 秒执行一次的测试任务。 5. 在 Django 项目的 wsgi.py 或者 asgi.py 文件启动 Apscheduler: ``` import os from django.core.wsgi import get_wsgi_application from apscheduler.schedulers.background import BackgroundScheduler os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings') application = get_wsgi_application() scheduler = BackgroundScheduler() scheduler.add_jobstore('django', 'default') scheduler.start() ``` 在这里,使用 BackgroundScheduler 启动 Apscheduler,并将默认的 jobstore 设置为 django,即使用 DjangoJobStore 存储定时任务信息。 通过以上步骤,就可以将 Apscheduler 的存储方式改为数据库存储,解决服务重启后定时任务失效的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值