Django通过celery实现任务注册和管理

Django接入Celery实现任务管理,并且启用flower进行任务的可视化查看。另外任务的结果除了保存在Redis中之外,我们也可以选在保存在MySQL等持久化数据库,方便后续做统计分析,结果查询等等操作

全栈运维 DailyJobOps - Django通过celery实现任务注册和管理


关于配置项的存放

按照官网提示的demo实现接入过程可能会遇到参数告警或者不生效的问题,原因在于

Celery will still be able to read old configuration files until Celery 6.0. Afterwards, support for the old configuration files will be removed. We provide the celery upgrade command that should handle plenty of cases (including Django).

也就是配置的时候两种方式配置项写法不一样

如果是在Django的settings配置文件中,写入采用CELERY_开头参数项都是大写的方式,比如

BROKER_URL = 'redis://127.0.0.1:6379'
CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379'
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TASK_SERIALIZER = 'json'
CELERY_TASK_TIME_OUT = 30 * 60
CELERY_TIMEZONE = 'Asia/Shanghai'

但是如果是在放到一个独立的配置文件中,比如这里demo演示的config.py

broker_url = 'redis://127.0.0.1:6379'
result_backend = 'redis://127.0.0.1:6379'
accept_content = ['application/json']
result_serializer = 'json'
task_serializer = 'json'
task_time_out = 30 * 60
timezone = 'Asia/Shanghai'
# imports = (
#     'celery_app.task_add',
# )

注意这里也可以手动指定导入那些task,如果项目中的task太多的时候我们都是按照一定的规范创建之后,采用app.autodiscover_tasks()实现

这里先上基础版的demo

目录结构如下, 这里忽略了Django默认创建的一些基本文件

demo_djcelery
├── cmdb
│   ├── __init__.py
| ... ...
│   ├── import_tasks.py
| ... ...
├── demo_djcelery
│   ├── __init__.py
| ... ...
│   ├── celery.py
│   ├── config.py
| ... ...
└── manage.py

这里需要特殊说明的是,注意 cmdb 应用下的 import_tasks.py ,这样命名是为了区分 手动导入自动发现

demo_djcelery/celery.py

# -*- coding: utf-8 -*-
from celery import Celery
from demo_djcelery import config 

app = Celery('DemoCelery')

# 这种通过模块的方式导入是需要添加引号
# app.config_from_object('demo_djcelery.config')
# 这种import的方式config是不需要添加引号的
app.config_from_object(config)

# app.autodiscover_tasks()
  • 这里的 app.autodiscover_tasks() 是注销的, 在如下config.py中启用了imports
  • 注意导入config对象两种方式的区别

config.py

broker_url = 'redis://127.0.0.1:6379/1'
result_backend = 'redis://127.0.0.1:6379/1'
accept_content = ['application/json']
result_serializer = 'json'
task_serializer = 'json'
task_time_out = 30 * 60
timezone = 'Asia/Shanghai'
imports = (
    'cmdb.import_tasks',
)

核心: 需要在 demo_djcelery 项目下的 init.py 中导入 celery app,目的是Django项目启动的时候能加载celery

from .celery import app as celery_app

__all__ = ('celery_app')

这个时候运行 celery -A demo_djcelery worker -l INFO 从结果中我们看到 task import_tasks 注册到了 celery

celery worker

思考题

在现有代码逻辑上,注销 config.py 中的imports配置,开启 celery.py中的 app.autodiscover_tasks() ,能否实现任务的自动注册呢?

休息5分钟我们继续... ...


_ _ _

摸鱼回来,我们继续...

上面的思考题,有没有尝试实践以下呢?

答案是无法注册任务 import_tasks。因为采用autodiscover的方式需要对任务创建有一定的要求

自动注册任务

在每个应用目录下创建一个tasks.py文件,文件的任务会会被自动注册到celery

这个时候我们在 cmdb 应用下新增 tasks.py 文件,内容如下

from celery import shared_task

@shared_task
def auto_task():
    print("auto register task from cmdb tasks.py")

然后注销 config.py 中的imports配置项,开启 celery.py 中的 app.autodiscover_tasks() 然后启动 celery worker看看有没有自动注册上任务 cmdb.tasks.auto_task

命令行输入如下命令,然后回车

celery -A demo_djcelery worker -l INFO

What happened??? 为啥也没有注册上呢?

大家先想想为什么呢?

不告诉你答案....
不告诉你答案....
不告诉你答案....

嗯,是否记得这节开头说的话

在每个应用目录下创建一个tasks.py文件,文件的任务会会被自动注册到celery

所以:

1、需要在Django的 INSTALLED_APPS 中注册上 cmdb
2、其实还有个关键的一步,就是在celery.py中配置os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'demo_djcelery.settings')
目的是为了让celery能获取Django的settings配置文件,找到找到都安装了那些应用,然后丛这些安装的应用下去查找tasks.py文件,进行任务的自动注册

配置任务结果写入MySQL数据库

结果写入我们知道是用result_backend配置项,之前我们配置的Redis,然后在Redis中可以看到任务执行的结果,类似如下:

7) "celery-task-meta-49b5034e-fa78-4bcf-b1ea-c9f990b2eb38"
8) "celery-task-meta-a58fa0ff-2051-47b2-b662-b191fdf2281e"
127.0.0.1:6379> get celery-task-meta-49b5034e-fa78-4bcf-b1ea-c9f990b2eb38
"{\"status\": \"SUCCESS\", \"result\": \"User Created\", \"traceback\": null, \"children\": [], \"date_done\": \"2022-01-30T06:28:26.109653\", \"task_id\": \"49b5034e-fa78-4bcf-b1ea-c9f990b2eb38\"}"

配置写入MySQL或者其他数据库,可以参考官网说明 https://docs.celeryproject.org/en/master/userguide/configuration.html#conf-database-result-backend

1、先安装相关第三方模块

pip install django-celery-results

2、然后配置到Django的 INSTALLED_APPS中,注意这里实际是下划线

INSTALLED_APPS = [
    ... ...,
    'cmdb',
    'django_celery_results',
]

3、 创建表

python manage.py migrate django_celery_results

4、然后在config.py中修改配置

result_backend = 'db+mysql://democelery:Democelery*2099@192.168.3.108:3306/demo_celery'

主要密码中不能有 @# 特殊符号,否则会报错

5、然后重启 celery worker,在进行测试就可以看到写入到数据了

mysql> select * from celery_taskmeta ;
+----+--------------------------------------+---------+-----------------------------+---------------------+-----------+------+------+--------+--------+---------+-------+
| id | task_id                              | status  | result                      | date_done           | traceback | name | args | kwargs | worker | retries | queue |
+----+--------------------------------------+---------+-----------------------------+---------------------+-----------+------+------+--------+--------+---------+-------+
|  1 | ea3f73d9-b3f4-41ef-a5eb-0beac8e599c2 | SUCCESS | ��       �
                                                                  User Created�.     | 2022-01-30 07:37:58 | NULL      | NULL | NULL | NULL   | NULL   |    NULL | NULL  |
+----+--------------------------------------+---------+-----------------------------+---------------------+-----------+------+------+--------+--------+---------+-------+
6 rows in set (0.05 sec)

这里需要注意:

虽然数据库migrate的时候生成了 表 django_celery_results_taskresult,但是最终却又自动生成了表celery_taskmeta,写入到该表种了。

刚开始自己在 taskresult 查了半天没有数据还以为哪里出错了...

celery flower

flower的具体介绍看官网就行 https://flower-docs-cn.readthedocs.io/zh/latest/ 这里不多说

目前flower已经集成在celery中,启动很简单

celery -A demo_djcelery flower

然后通过本地的5555端口就可以访问

参考

Celery接入Django
Celery配置项及数据库ResultBackend

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容