利用Django和Celery管理定时任务
一、背景介绍
我们以前一直使用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, 创建成功之后我们会得到如下的一个目录结构:
1 | proj |
熟悉Django的人应该对上面这个目录树非常熟悉,下面的内容都是基于这个目录树写的,所以需要记住这个目录树。
1. 定义Celery实例
为了定义Celery实例,需要在上面的目录树中创建一个文件: proj/proj/celery.py。
这个文件名是celery.py,跟settings.py在同一层目录。
内容如下,我把一些很重要的信息以注释的形式写在代码里了,注意查看。
1 | import os |
2. 记录任务的结果
用celery做任务调度的时候可以最好能把每一次任务的结果记录下来,以便以后查阅,尤其是当任务没有按照预期运行的时候,这一点更加重要。
官网推荐使用django-celery-results做记录任务结果。
- 安装
pip install django-celery-results
- 注册
django-celery-results是一个单独的django的app,所以需要在settings.py注册一下1
2
3
4
5
6
7
8
9
10
11
12
13
14INSTALLED_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目录下运行,不然会报错,提示找不到配置文件之类的错误1
celery -A backend worker --loglevel=INFO
三、定时任务配置
前面介绍了怎么样配置celery,现在celery有了,要怎么来管理定时任务呢?这个时候就要用到django-celery-beat了,它的使用比较简单。
1. 配置django-celery-beat
- 安装
pip install django-celery-beat
- 注册
在django的settings.py中进行注册1
2
3
4
5
6
7
8
9
10
11INSTALLED_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页面之后通过页面点击创建即可,不难,但是想写出来要接很多图,就不是很想写了。