前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >利用Django和Celery管理定时任务

利用Django和Celery管理定时任务

作者头像
panzhixiang
发布2024-10-30 19:23:32
发布2024-10-30 19:23:32
12600
代码可运行
举报
文章被收录于专栏:panzhixiang
运行总次数:0
代码可运行

一、背景介绍

我们以前一直使用k8s的cronjob来管理定时任务的。把定时任务相关的代码单独封装成一个pod,然后以cronjob的方法来触发。

虽然这个方法操作很简单,没有什么第三方资源的依赖(比如Redis),但是也有一个明显的缺点。

定时任务的代码脱离了Django代码,也就不能使用Django的很多功能了,只能通过DRF封装的API来跟Django的Server通信。 有的时候为了一个定时任务,要封装很多API,还要考虑鉴权等问题,也挺麻烦的,所以就在新项目中打算换一个方法来做定时任务的管理。

同时使用Python和Django的工程师估计基本都知道Celery,它是一个很好的异步任务框架。我上一次使用它还是2020年,发现这几年Celery的使用方法发生了一些变化,在网上找了一圈也没有找到很好的中文资料,所以自己写一篇相关的博客,希望能给以后需要查询相关信息的人提供一点帮助。

二、Celery配置

在配置Celery之前需要先安装,pip install celery, 接下来就开始配置了。

在正式开始介绍配置之前,我们需要一些假设,以便下面的文字可以表述的更清楚。

我们以django-admin startproject proj创建一个Django项目,Django版本应当>=3.0, 创建成功之后我们会得到如下的一个目录结构:

代码语言:javascript
代码运行次数:0
复制
proj
├── manage.py
└── proj
    ├── asgi.py
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    └── wsgi.py

熟悉Django的人应该对上面这个目录树非常熟悉,下面的内容都是基于这个目录树写的,所以需要记住这个目录树。

1. 定义Celery实例

为了定义Celery实例,需要在上面的目录树中创建一个文件: proj/proj/celery.py。 这个文件名是celery.py,跟settings.py在同一层目录。

内容如下,我把一些很重要的信息以注释的形式写在代码里了,注意查看。

代码语言:javascript
代码运行次数:0
复制
import os
from celery import Celery


# 这个配置可以避免在其他的tasks.py中初始化django配置,虽然不是必须的,但是强烈建议要有这个配置
os.environ.setdefault(
    'DJANGO_SETTINGS_MODULE', 'proj.settings'
)

# 这个就是从环境变量中获取redis的地址,我这里使用redis作为broker
REDIS_HOST = os.getenv('REDIS_HOST', 'localhost:6379')
app = Celery(
    'proj',  # 第一个参数是为celery的实例起了一个名字,这里叫做proj
    backend='redis://' + REDIS_HOST + '/1',
    broker='redis://' + REDIS_HOST + '/0',
)

# 可以用这个方法批量配置celery,
# 这几个配置在一帮的场景中就足够使用了
# 另外,其实还有几种其他方法来配置celery,但是我觉得这个方法对于不是非常大的项目来说就足够了。
app.conf.update(
    task_serializer='json',
    accept_content=['json'],  # Ignore other content
    result_serializer='json',
    enable_utc=True,
)

# 这一行会从django的settings文件中获取一些celery的配置
# namespace等于CELERY的意思是settings中以 “CELERY_” 开头的配置都会被识别为celery的配置
app.config_from_object('django.conf:settings', namespace='CELERY')

# 会自动发现所有Django app中的任务
app.autodiscover_tasks()


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

除了上面这个配置,还有两个地方需要配。  
首先是需要在**proj/proj/\_\_init\_\_.py**中添加以下内容:
```python
from .celery import app as celery_app


__all__ = ('celery_app',)
```  
它的作用是在启动Django的时候自动加载celery。  

还有一个就是需要在django的settings中添加celery的配置,也就是上面代码中`app.config_from_object('django.conf:settings', namespace='CELERY')` 提到的部分。  
```python
CELERY_TASK_TRACK_STARTED = True
CELERY_TASK_TIME_LIMIT = 30 * 60  # 单个任务的最大运行时间,单位是秒

2. 记录任务的结果

用celery做任务调度的时候可以最好能把每一次任务的结果记录下来,以便以后查阅,尤其是当任务没有按照预期运行的时候,这一点更加重要。

官网推荐使用django-celery-results做记录任务结果。

安装 pip install django-celery-results

注册 django-celery-results是一个单独的django的app,所以需要在settings.py注册一下

代码语言:javascript
代码运行次数:0
复制
    INSTALLED_APPS = (
        ...,
        'django_celery_results',
    )
    ```  
    注册之后还需要迁移数据库,
    `python manage.py migrate django_celery_results`
3. 配置
django-celery-results只是一个帮助自动存储任务结果的包,最终数据还需要一个地方落地,有很多地方都可以用来存储任务结果,比如数据库、本地文件系统,redis等等,我这里使用数据库,也比较推荐使用数据库。  
在django的setting.py中添加一下配置:
    ```python
    CELERY_RESULT_BACKEND = 'django-db'  # 使用数据库做后端
    CELERY_CACHE_BACKEND = 'django-cache'  # 老实说,不知道这个缓存配置到底有什么作用,但是官网推荐使用这个配置,我也就留着了
    CELERY_CACHE_BACKEND = 'default'

启动 注意这个命令要在第一层proj目录下运行,不然会报错,提示找不到配置文件之类的错误

代码语言:javascript
代码运行次数:0
复制
celery -A backend worker --loglevel=INFO

三、定时任务配置

前面介绍了怎么样配置celery,现在celery有了,要怎么来管理定时任务呢?这个时候就要用到django-celery-beat了,它的使用比较简单。

1. 配置django-celery-beat

安装 pip install django-celery-beat

注册 在django的settings.py中进行注册

代码语言:javascript
代码运行次数:0
复制
    INSTALLED_APPS = (
        ...,
        'django_celery_beat',
    )
    ```   
    同样,注册之后要迁移数据库,
    `python manage.py migrate django-celery-beat`
3. 启动  
    **注意这个命令要在第一层proj目录下运行,不然会报错,提示找不到配置文件之类的错误**
    ```sh
    celery -A proj beat -l INFO --scheduler django_celery_beat.schedulers:DatabaseScheduler

想要单独说明的是,很多人在使用django_celery_beat做定时任务管理的时候,喜欢把定时任务以cronjob的形式封装在代码中,但是我比较喜欢通过Django Admin页面在数据库中进行配置。

因为封装在代码中,以后如果想要修改定时任务,就需要重新写代码然后部署到环境中,不太友好,而且对于非技术人员来说,想要自己配置定时任务的可能性几乎为零。

2. 通过Django Admin设置具体的定时任务

这一部分内容比较简单,把Django启动,登录到Admin页面之后通过页面点击创建即可,不难,但是想写出来要接很多图,就不是很想写了。

四、参考

  1. First Steps with Django
  2. Task result backend settings
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-03-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、背景介绍
  • 二、Celery配置
    • 1. 定义Celery实例
    • 2. 记录任务的结果
  • 三、定时任务配置
    • 1. 配置django-celery-beat
    • 2. 通过Django Admin设置具体的定时任务
  • 四、参考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档