Django+Celery+xadmin实现异步任务和定时任务

关注公众号“轻松学编程”了解更多。

一、celery介绍

1、简介

【官网】http://www.celeryproject.org/

Celery 是一个强大的分布式任务队列,它可以让任务的执行完全脱离主程序,甚至可以被分配到其他主机上运行。我们通常使用它来实现异步任务( async task )和定时任务( crontab )。

  • 异步任务:比如发送邮件、短信,或者文件上传, 图像处理等等一些比较耗时的操作 ;
  • 定时任务:需要在特定时间执行的任务。

架构组成如图:

2、Celery 主要包含以下几个模块

2.1 任务模块 Task

异步任务通常在业务逻辑中被触发并发往任务队列;

定时任务由 Celery Beat 进程周期性地将任务发往任务队列。

2.2 消息中间件 Broker

Broker,即为任务调度队列,接收任务生产者发来的消息(即任务),将任务存入队列。
Celery 本身不提供队列服务,官方推荐使用 RabbitMQ 和 Redis 等。

2.3 任务执行单元 Worker

Worker 是执行任务的处理单元,它实时监控消息队列,获取队列中调度的任务,并执行它。

2.4 任务结果存储 Backend

Backend 用于存储任务的执行结果,以供查询。同消息中间件一样,存储也可使用RabbitMQ, Redis 和 MongoDB 等。
MQ全称为Message Queue。

消息队列(MQ)是不同的应用程序相互通信的一种方法。

MQ是消费者-生产者模型的一个典型的代表,一端往消息队列中不断写入消息,而另一端则可以读取队列中的消息。

二、异步任务

假设已经有了一个Django项目(我的项目名是MySites),下面演示如何使用Celery实现异步任务。

1、安装celery

  1. pip install celery
  2. pip install django-celery
  3. pip install redis==2.10.6
  4. pip install django_celery_beat

注意:如果出现以下错误,一般是celery版本不对,重新安装较高版本即可。

  1. Running django in virtualenv - ImportError: No module name django.core.management

2、配置settings.py

我使用Redis作为消息队列。

在settings.py中增加:

  1. #django-celery
  2. import djcelery
  3. djcelery.setup_loader()
  4. #使用本地redis服务器中的0号数据库,redis密码为123456
  5. BROKER_URL = 'redis://:123456@127.0.0.1:6379/0'
  6. CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler'
  7. CELERY_RESULT_BACKEND = 'redis://:123456@127.0.0.1:6379/1'
  8. CELERY_ENABLE_UTC = False
  9. CELERY_TIMEZONE = 'Asia/Shanghai'
  10. CELERY_TASK_RESULT_EXPIRES = 10
  11. CELERYD_LOG_FILE = BASE_DIR + "/logs/celery/celery.log"
  12. CELERYBEAT_LOG_FILE = BASE_DIR + "/logs/celery/beat.log"
  13. CELERY_ACCEPT_CONTENT = ['pickle', 'json', 'msgpack', 'yaml']

其中,当djcelery.setup_loader()运行时,Celery便会去查看INSTALLD_APPS下包含的所有app目录中的tasks.py文件,找到标记为task的方法,将它们注册为celery_task。

BROKER_URL和CELERY_RESULT_BACKEND分别指代你的Broker的代理地址以及Backend(result store)数据存储地址。

在Django中如果没有设置backend,会使用其默认的后台数据库用来存储数据。

注册celery应用:

  1. INSTALLED_APPS = [
  2. #其它应用
  3. ...
  4. #celery应用
  5. 'djcelery',
  6. ]

3、创建celery.py文件

在项目中Mysites下创建celery.py文件(与settings.py同级)

内容为:

  1. from celery import Celery
  2. from django.conf import settings
  3. import os
  4. # 为celery设置环境变量, 改为你项目的settings
  5. os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'MySites.settings')
  6. # 创建应用
  7. app = Celery('mysites')
  8. # 配置应用
  9. app.conf.update(
  10. # 本地Redis服务器
  11. BROKER_URL=settings.BROKER_URL,
  12. )
  13. app.autodiscover_tasks(settings.INSTALLED_APPS)

4、创建tasks.py文件

在子应用app下创建tasks.py:

内容为:

  1. from MySites.celery import app
  2. @app.task
  3. def start_running(info):
  4. print(info)
  5. print('--->>开始执行任务<<---')
  6. print('比如发送短信或邮件')
  7. print('>---任务结束---<')

5、修改views.py

在views.py中增加需要执行的异步任务,比如:

  1. from SitesApp.tasks import start_running
  2. #celery测试
  3. class CeleryTask(View):
  4. def get(self, request):
  5. print('>=====开始发送请求=====<')
  6. start_running.delay('发送短信')
  7. # start_running.apply_async(('发送短信',), countdown=10) # 10秒后再执行异步任务
  8. return HttpResponse('<h2> 请求已发送 </h2>')

其实关键代码就一条start_running.delay(参数),当执行这条代码时,系统会把tasks.py中的start_running函数推迟执行,即放入消息队列中。

系统相当于跳过start_running.delay('发送短信')执行后面的语句,这就是异步任务。

6、修改项目下(不是子应用下)的urls.py

  1. from SitesApp import views
  2. urlpatterns = [
  3. #其它url
  4. ...
  5. #celery测试url
  6. url('^celery/',views.CeleryTask.as_view()),
  7. ]

7、启动服务

在Terminal中输入:

  1. python manage.py runserver

在另一个Terminal中:

  1. celery -A MySites worker --loglevel=DEBUG


8、查看异步任务情况

Celery提供了一个工具flower,将各个任务的执行情况、各个worker的健康状态进行监控并以可视化的方式展现,如下图所示:


下实现的方式如下:

  1. 安装flower:

    1. pip install flower
  2. 启动flower(默认会启动一个webserver,端口为5555):

    在另一个Terminal中:

    1. python manage.py celery flower

3.进入http://localhost:5555即可查看。

9、一些错误解决方法

错误1:

  1. Celery ValueError: not enough values to unpack (expected 3, got 0)

看别人描述大概就是说win10上运行celery4.x就会出现这个问题,解决办法如下,原理未知:

先安装一个``eventlet`

  1. pip install eventlet

启动worker时加上参数-P eventlet

  1. celery -A MySites worker --loglevel=DEBUG -P eventlet

三、定时任务

1、配置settings.py

注册django_celery_beat应用:

  1. INSTALLED_APPS = [
  2. #其它应用
  3. ...
  4. #django_celery_beat应用
  5. 'django_celery_beat',
  6. ]

2、配置项目目录下的__init__()

  1. from __future__ import absolute_import
  2. from MySites.celery import app as celery_app
  3. import pymysql
  4. pymysql.install_as_MySQLdb()

3、修改celery.py文件

修改项目目录(和settings.py)同级的celery.py:

  1. from __future__ import absolute_import
  2. import os
  3. from celery import Celery, platforms
  4. from django.conf import settings
  5. # set the default Django settings module for the 'celery' program.
  6. os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'MySites.settings')
  7. # MySites主应用名
  8. app = Celery('mysites')
  9. platforms.C_FORCE_ROOT = True
  10. # 配置应用
  11. app.conf.update(
  12. # 本地Redis服务器
  13. BROKER_URL=settings.BROKER_URL,
  14. )
  15. app.config_from_object('django.conf:settings')
  16. app.autodiscover_tasks(settings.INSTALLED_APPS)
  17. @app.task(bind=True)
  18. def debug_task(self):
  19. print('Request: {0!r}'.format(self.request))

4、修改adminx.py文件

我使用xadmin作为后台管理。增加以下代码:

  1. #adminx.py
  2. from __future__ import absolute_import, unicode_literals
  3. from djcelery.models import (
  4. TaskState, WorkerState,
  5. PeriodicTask, IntervalSchedule, CrontabSchedule,
  6. )
  7. #celery
  8. xadmin.site.register(IntervalSchedule) # 存储循环任务设置的时间
  9. xadmin.site.register(CrontabSchedule) # 存储定时任务设置的时间
  10. xadmin.site.register(PeriodicTask) # 存储任务
  11. xadmin.site.register(TaskState) # 存储任务执行状态
  12. xadmin.site.register(WorkerState) # 存储执行任务的worker

5、修改tasks.py文件

  1. from __future__ import absolute_import
  2. from MySites.celery import app
  3. from celery import task, shared_task
  4. @app.task
  5. def start_running(info):
  6. print(info)
  7. print('--->>开始执行任务<<---')
  8. print('比如发送短信或邮件')
  9. print('>---任务结束---<')
  10. @task
  11. def pushMsg(uid,msg):
  12. print('推送消息',uid,msg)
  13. return True
  14. @shared_task
  15. def add(x,y):
  16. print('加法:',x + y)
  17. return x + y
  18. @shared_task
  19. def mul(x, y):
  20. print('乘法',x*y)
  21. return x * y

6、数据库迁移和创建管理员

  1. python manage.py makemigrations
  2. python manage.py migrate
  3. python manage.py createsuperuser

8、启动服务器

  1. python manage.py runserver

在浏览器打开http://127.0.0.1:10501/xadmin/

Crontabs:定时任务执行时间;

Intervals:简单的间隔执行时间,比如每10秒执行一次;

Periodic tasks:配置定时任务;

Tasks:任务监控;

Workers:运行的worker。

配置执行时间:


添加定时任务:

9、终端启动celery命令


  1. # 启动
  2. #linux下
  3. celery -A MySites worker -B # MySites为celery和setting所在文件夹名
  4. #Windows下先启动celery-beat
  5. celery -A MySites beat -l debug --max-interval=10
  6. #然后再启动worker
  7. celery -A MySites worker -l debug -P eventlet
  8. #注意:在正式环境下把debug改为info
  9. # 查看注册的task
  10. celery -A MySites inspect registered
  11. # flower监控celery
  12. celery flower
  13. ip:5555

注意:出现以下错误是windows不支持celery4.0以上版本,降低为3.1版本即可

  1. SystemError: <class 'OSError'> returned a result with an error set
  1. pip uninstall celery
  2. pip install celery==3.1.22

补充:celery4.0以上版本不再支持 Microsoft Windows ,不再支持使用Django ORM作为代理 。

10、服务器使用Supervisor后台运行Celery

  1. pip install supervisor

我们可以使用echo_supervisord_conf命令得到supervisor配置模板,打开终端执行如下Linux shell命令:

  1. echo_supervisord_conf > supervisord.conf

该命令输出文件到当前目录下(当然,你也可以指定绝对路径到具体位置),文件名为supervisord.conf
修改supervisord.conf文件,在文件最后加入:

  1. [program:celery.worker]
  2. ;指定运行目录
  3. directory=/home/你的项目名称
  4. ;运行目录下执行命令
  5. command=celery -A 你的项目名称worker --loglevel info --logfile celery_worker.log
  6. ;启动设置
  7. numprocs=1 ;进程数
  8. autostart=true ;当supervisor启动时,程序将会自动启动
  9. autorestart=true ;自动重启
  10. ;停止信号,默认TERM
  11. ;中断:INT (类似于Ctrl+C)(kill -INT pid),退出后会将写文件或日志(推荐)
  12. ;终止:TERM (kill -TERM pid)
  13. ;挂起:HUP (kill -HUP pid),注意与Ctrl+Z/kill -stop pid不同
  14. ;从容停止:QUIT (kill -QUIT pid)
  15. stopsignal=INT
  16. ;输出日志
  17. stdout_logfile=celery_worker.log
  18. stdout_logfile_maxbytes=10MB ;默认最大50M
  19. stdout_logfile_backups=10 ;日志文件备份数,默认为10
  20. ;错误日志
  21. redirect_stderr=false ;为true表示禁止监听错误
  22. stderr_logfile=celery_worker_err.log
  23. stderr_logfile_maxbytes=10MB
  24. stderr_logfile_backups=10

启动supervisor输入如下命令,使用具体的配置文件执行:
先运行虚拟环境

  1. supervisord -c supervisord.conf

关闭supervisor输入如下命令:

  1. supervisorctl -c supervisord.conf shutdown

重启supervisor输入如下命令:

  1. supervisorctl -c supervisord.conf reload

后记

【后记】为了让大家能够轻松学编程,我创建了一个公众号【轻松学编程】,里面有让你快速学会编程的文章,当然也有一些干货提高你的编程水平,也有一些编程项目适合做一些课程设计等课题。

也可加我微信【1257309054】,拉你进群,大家一起交流学习。
如果文章对您有帮助,请我喝杯咖啡吧!

公众号

关注我,我们一起成长~~

【参考文章】:
http://yshblog.com/blog/165
https://www.jb51.net/article/133507.htm

https://blog.csdn.net/Shyllin/article/details/80940643

https://www.cnblogs.com/znicy/p/5626040.html

https://blog.csdn.net/qq_30242609/article/details/79047660

https://www.jb51.net/article/145573.htm

https://www.cnblogs.com/dengshihuang/p/8258621.html

https://blog.csdn.net/yeyingcai/article/details/78647553

http://www.manongjc.com/article/5685.htmlhttps://www.cnblogs.com/huangxiaoxue/p/7266253.html

https://blog.csdn.net/xiemanr/article/details/70331120

http://www.linuxdiyf.com/viewarticle.php?id=562707

Django+Celery+xadmin实现异步任务和定时任务的更多相关文章

  1. 基于Django+celery二次开发动态配置定时任务 ( 一 )

    需求: 前端时间由于开发新上线一大批系统,上完之后没有配套的报表系统.监控,于是乎开发.测试.产品.运营.业务部.财务等等各个部门就跟那饥渴的饿狼一样需要 各种各样的系统数据满足他们.刚开始一天一个还 ...

  2. 基于Django+celery二次开发动态配置定时任务 ( 二)

    一.需求 结合上一篇,使用djcelery模块开发定时任务时,定时任务的参数都保存在djcelery_periodictask表的args.kwargs字段里,并且是json格式.那么,当定时任务多了 ...

  3. django celery的分布式异步之路(一) 起步

    如果你看完本文还有兴趣的话,可以看看进阶篇:http://www.cnblogs.com/kangoroo/p/7300433.html 设想你遇到如下场景: 1)高并发 2)请求的执行相当消耗机器资 ...

  4. django celery的分布式异步之路(二) 高并发

    当你跑通了前面一个demo,博客地址:http://www.cnblogs.com/kangoroo/p/7299920.html,那么你的分布式异步之旅已经起步了. 性能和稳定性是web服务的核心评 ...

  5. Django+Celery+Redis实现异步任务(发送邮件)

    安装如下依赖库 pip install Celery pip install django-celery pip install django-redis 还要安装本地的Redis服务 setting ...

  6. django+celery+ RabbitMQ实现异步任务实例

    背景   django要是针对上传文件等需要异步操作的场景时,celery是一个非常不错的选择.笔者的项目就是使用了这个组合,这里就做一个备忘吧. 安装RabbitMQ   这个安装及使用我已经在前一 ...

  7. 如何使用django+celery+RabbitMQ实现异步执行

    1)安装需要安装RabbitMQ.Celery和Django-celeryCelery和Django-celery的安装直接pip就好 2)修改settings.py在INSTALLED_APPS中加 ...

  8. 使用django+celery+RabbitMQ实现异步执行

    http://www.yu180.com/group/view/259 推荐一个解决框架 https://github.com/maccman/juggernaut Realtime server p ...

  9. Django+Celery 执行异步任务和定时任务

    celery是一个基于python开发的简单.灵活且可靠的分布式任务队列框架,支持使用任务队列的方式在分布式的机器/进程/线程上执行任务调度.采用典型的生产者-消费者模型,主要由三部分组成: 1. 消 ...

随机推荐

  1. 【Vulhub】CVE-2019-3396 Confluence RCE漏洞复现

    CVE-2019-3396 Confluence RCE漏洞复现 一.环境搭建 选择的vulhub里的镜像,进入vulhub/Confluence/CVE-2019-3396目录下,执行 docker ...

  2. go分库分表 主从分离例子

    网上有很多介绍分库分表的文章,方法很多: 分区表切分 垂直切分 水平切分 区间切分 取模切分 这里不细说 分库分表简单,但后期会带来一系列的难题: 事务 Join 分页 数据库: master和sla ...

  3. 日志分析平台ELK之日志收集器filebeat

    前面我们了解了elk集群中的logstash的用法,使用logstash处理日志挺好的,但是有一个缺陷,就是太慢了:当然logstash慢的原因是它依赖jruby虚拟机,jruby虚拟机就是用java ...

  4. 排序算法:归并排序(Merge Sort)

    归并排序 归并排序采用了分治策略(divide-and-conquer),就是将原问题分解为一些规模较小的相似子问题,然后递归解决这些子问题,最后合并其结果作为原问题的解. 归并排序将排序数组A[1. ...

  5. 036 01 Android 零基础入门 01 Java基础语法 04 Java流程控制之选择结构 03 嵌套if结构

    036 01 Android 零基础入门 01 Java基础语法 04 Java流程控制之选择结构 03 嵌套if结构 本文知识点:Java中的嵌套if结构 什么是嵌套if结构? 概念: 嵌套if结构 ...

  6. 【代码审计】PHP代码审计---基础记录

    PHP伪协议 PHP伪协议事实上是其支持的协议与封装协议,支持的种类有以下12种. * file:// - 访问本地文件系统 * http:// - 访问 HTTP(s) 网址 * ftp:// - ...

  7. 【题解】[SDOI2015]星际战争

    \(\color{red}{Link}\) \(\text{Solution:}\) 观察到,如果一个时间\(T\)可以完成任务,则\(T+1\)这个时间也可以完成任务. 于是我们可以二分. 为了避免 ...

  8. 一文带你定制unittest测试用例的名称

    在之前的文章中,我在之前的文章中提到过,这里呢,考虑后,感觉之前的写法不够优雅,于是乎呢,我自己抽空去研究了下,主要是新写方法,这样呢,以后的要使用的时候,可以直接去使用,而不是每次换个环境就要修改环 ...

  9. Docker笔记2:Docker 镜像仓库

    Docker 镜像的官方仓库位于国外服务器上,在国内下载时比较慢,但是可以使用国内镜像市场的加速器(比如阿里云加速器)以提高拉取速度. Docker 官方的镜像市场,可以和 Gitlab 或 GitH ...

  10. 超好用的UnixLinux 命令技巧 大神为你详细解读

    1.删除一个大文件 我在生产服务器上有一个很大的200GB的日志文件需要删除.我的rm和ls命令已经崩溃,我担心这是由于巨大的磁盘IO造成的,要删除这个大文件,输入: > /path/to/fi ...