一、celery简介:

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

Celery的架构由三部分组成,消息中间件(message broker),任务执行单元(worker)和任务执行结果存储(task result store)组成。

可以看到,Celery 主要包含以下几个模块:

  • 任务模块 Task

    包含异步任务和定时任务。其中,异步任务通常在业务逻辑中被触发并发往任务队列,而定时任务由 Celery Beat 进程周期性地将任务发往任务队列。

  • 消息中间件 Broker

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

  • 任务执行单元 Worker

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

  • 任务结果存储 Backend

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

所以总结一下celery:它是一个处理大量消息的分布式系统,能异步任务、定时任务,使用场景一般用于耗时操作的多任务或者定时性的任务

二、celery安装与使用

pycharm安装:

  1. pip3 install celery

初步使用:(创建一个Python项目)

① 实例化一个celery对象,使用该对象.task装饰需要管理的任务函数:

  1. # celery_task.py
  2.  
  3. from celery import Celery
  4.  
  5. """
  6. # 如果redis没有设置密码
  7. broker = 'redis://127.0.0.1:6379/1'
  8. backend = 'redis://127.0.0.1:6379/2'
  9. """
  10. broker = 'redis://:12345@127.0.0.1:6379/1'
  11. backend = 'redis://:12345@127.0.0.1:6379/2'
  12. # c1是实例化产生的celery的名字,因为会存在多个celery
  13. app = Celery('c1', broker=broker, backend=backend)
  14.  
  15. # 需要使用一个装饰器,来管理该任务(函数)
  16. @app.task
  17. def add(x, y):
  18. import time
  19. time.sleep(1)
  20. return x + y

② 将装饰的任务函数条件到消息队列中,此时提交的任务函数并没有执行,只是提交到worker,它会返回一个标识任务的字符串

  1. # submit.task.py
  2.  
  3. # 用于提交任务
  4. from celery_task import add
  5. # 提交任务到消息队列中,这里只是将任务提交,并没有执行
  6.  
  7. res = add. delay(3, 8)
  8. print(res)
  9. # 结果是标识任务的字符串(id号)
  10. # 7811a028-428c-4dd5-9135-788e26e694a7

③ 使用命令启动worker去刚才提交的执行任务

  1. linux: celery worker -A celery_task -l info
  2. windows下:celery worker -A celery_task -l info -P eventlet

④ 查看结果,根据提交任务返回的字符串去查询

  1. # check_res.py
  2.  
  3. from celery.result import AsyncResult
  4. from celery_task import app
  5.  
  6. async = AsyncResult(id='bd600820-9366-4220-a679-3e435ae91e71', app=app)
  7.  
  8. if async.successful():
  9. result = async.get()
  10. print(result)
  11.  
  12. elif async.failed():
  13. print('执行失败')
  14.  
  15. elif async.status == 'PENDING':
  16. print('任务等待中')
  17.  
  18. elif async.status == 'RETRY':
  19. print('任务异常后重试')
  20.  
  21. elif async.status == 'STARTED':
  22. print('任务正在执行')

celery简单使用流程:

  1. -celery的使用
  2. -pip3 install celery
  3. -写一个py文件:celery_task
  4. -1 指定broker(消息中间件),指定backend(结果存储)
  5. -2 实例化产生一个Celery对象 app=Celery('名字'brokerbackend)
  6. -3 加装饰器绑定任务,在函数(add)上加装饰器app.task
  7. -4 其他程序提交任务,先导入addadd.delay(参,参数),会将该函数提交到消息中间件,但是并不会执行,有个返回值,直接print会打印出任务的id,以后用id去查询任务是否执行完成
  8. -5 启动worker去执行任务:
  9. linux: celery worker -A celery_task_s1 -l info
  10. windows下:celery worker -A celery_task_s1 -l info -P eventlet
  11. -6 查看结果:根据id去查询
  12. async = AsyncResult(id="bd600820-9366-4220-a679-3e435ae91e71", app=app)
  13. if async.successful():
  14. #取出它return的值
  15. result = async.get()
  16. print(result)

celery的多任务

  1. # celery的多任务结构
  2. -项目结构:
  3. pro_cel
  4. ├── celery_task# celery相关文件夹
  5. ├── celery.py # celery连接和配置相关文件,必须叫这个名字
  6. └── tasks1.py # 所有任务函数
  7. └── tasks2.py # 所有任务函数
  8. ├── check_result.py # 检查结果
  9. └── send_task.py # 触发任务
  10. -启动workercelery_task是包的名字
  11. celery worker -A celery_task -l info -P eventlet

按照多任务文件结构创建文件:

注意celery.py这个文件的文件名是固定的,不能改,task_1和task_2可以自己定义,他俩代表自定义的任务分类,还可以再创建task_3。。。等其它名字的任务文件,send_task.py是提交任务到worker,check_result.py是查看结果的

  1. # celery.py
  2.  
  3. from celery import Celery
  4. broker = 'redis://:12345@127.0.0.1:6379/1'
  5. backend = 'redis://:12345@127.0.0.1:6379/2'
  6. # c1是实例化产生的celery的名字,因为会存在多个celery
  7. app = Celery('c1', broker=broker, backend=backend,
  8. # 包含一些2个任务文件,去相应的py文件找任务,对多个任务进行分类
  9. include=[
  10. 'celery_task.task_1',
  11. 'celery_task.task_2',
  12. ])
  13.  
  14. # celery提供一些配置,具体可查看官方文档
  15. # app.conf.timezone = 'Asia/Shanghai'

在send_task.py种右键运行,提交任务到worker(这里打印了提交的2个任务的id)

  1. # task_1.py
  2. from celery_task.celery import app
  3.  
  4. @app.task
  5. def add1(x, y):
  6. import time
  7. time.sleep(0.5)
  8. return x + y
  9.  
  10. # task_2.py
  11. from celery_task.celery import app
  12.  
  13. @app.task
  14. def add2(x, y):
  15. import time
  16. time.sleep(1)
  17. return x * y
  1. # send_task.py
  2. from celery_task.task_1 import add1
  3. from celery_task.task_2 import add2
  4.  
  5. res1 = add1.delay(3, 8)
  6. print(res1) # 16e847f3-fc14-4391-89e2-e2b3546872cf
  7.  
  8. res2 = add2.delay(4, 9)
  9. print(res2) # 858c0ae5-8516-4473-8be5-7501fb856ff4

启动worker,celery_task是包的名字
celery worker -A celery_task -l info -P eventlet

然后将打印的2个id在check_result.py中进行查询结果

  1. # check_reslut.py
  2. from celery.result import AsyncResult
  3. from celery_task.celery import app
  4.  
  5. for i in ['16e847f3-fc14-4391-89e2-e2b3546872cf', '858c0ae5-8516-4473-8be5-7501fb856ff4']:
  6. async = AsyncResult(id=i, app=app)
  7. if async.successful():
  8. result = async.get()
  9. print(result)
  10.  
  11. elif async.failed():
  12. print('执行失败')
  13.  
  14. elif async.status == 'PENDING':
  15. print('任务等待中')
  16.  
  17. elif async.status == 'RETRY':
  18. print('任务异常后重试')
  19.  
  20. elif async.status == 'STARTED':
  21. print('任务正在执行')

celery的定时任务

方式一:执行时间在年月日时分秒

在提交任务的地方修改:

  1. # send_task.py
  2.  
  3. from celery_task.task_1 import add1
  4. from celery_task.task_2 import add2
  5. # 执行定时任务,3s以后执行add1、add2任务
  6. from datetime import datetime
  7. # 设置任务执行时间2019年7月12日21点45分12秒
  8. v1 = datetime(2019, 7, 12, 21, 48, 12)
  9. print(v1) # 2019-07-12 21:45:12
  10. # 将v1时间转成utc时间
  11. v2 = datetime.utcfromtimestamp(v1.timestamp())
  12. print(v2) # 2019-07-12 13:45:12
  13. # 取出要执行任务的时间对象,调用apply_async方法,args是任务函数传的参数,eta是执行的时间
  14. result1 = add1.apply_async(args=[3, 8], eta=v2)
  15. result2 = add2.apply_async(args=[4, 9], eta=v2)
  16. print(result1.id)
  17. print(result2.id)

方式二:通过延迟执行的时间算出执行的具体utc时间,与方式一基本相同

在提交任务的地方修改:

  1. # send_task.py
  2.  
  3. # 方式二:实际上和方法一类似,多了一个延迟时间,也就是用现在时间和推迟执行的时间计算出任务执行的最终utc时间
  4. # 然后也是调用apply_async方法。
  5. from datetime import datetime
  6. ctime = datetime.now()
  7. # 默认使用utc时间
  8. utc_ctime = datetime.utcfromtimestamp(ctime.timestamp())
  9. from datetime import timedelta
  10. # 使用timedelta模块,拿到10秒后的时间对象,这里参数可以传秒、毫秒、微秒、分、小时、周、天
  11. time_delay = timedelta(seconds=10)
  12. # 得到任务运行时间:
  13. task_time = utc_ctime + time_delay
  14. result1 = add1.apply_async(args=[3, 8], eta=task_time)
  15. result2 = add2.apply_async(args=[4, 9], eta=task_time)
  16. print(result1.id)
  17. print(result2.id)

celery的计划任务

计划任务需要在celery.py中添加代码,然后需要beat一下,才能将计划开启

  1. # celery.py中
  2.  
  3. from celery import Celery
  4. broker = 'redis://:12345@127.0.0.1:6379/1'
  5. backend = 'redis://:12345@127.0.0.1:6379/2'
  6. # c1是实例化产生的celery的名字,因为会存在多个celery
  7. app = Celery('c1', broker=broker, backend=backend,
  8. # 包含一些2个任务文件,去相应的py文件找任务,对多个任务进行分类
  9. include=[
  10. 'celery_task.task_1',
  11. 'celery_task.task_2',
  12. 'celery_task.task_3',
  13. ])
  14.  
  15. # celery提供一些配置,具体可查看官方文档
  16. # app.conf.timezone = "Asia/Shanghai"
  17. # app.conf.enable_utc = True
  18.  
  19. # 计划任务
  20. from datetime import timedelta
  21. from celery.schedules import crontab
  22. app.conf.beat_schedule = {
  23. 'submit_every_2_seconds': {
  24. # 计划的任务执行函数
  25. 'task': 'celery_task.task_1.add1',
  26. # 每个2秒执行一次
  27. 'schedule': timedelta(seconds=2),
  28. # 传递的任务函数参数
  29. 'args': (3, 9)
  30. },
  31. 'submit_every_3_seconds': {
  32. # 计划的任务执行函数
  33. 'task': 'celery_task.task_2.add2',
  34. # 每个3秒执行一次
  35. 'schedule': timedelta(seconds=3),
  36. # 传递的任务函数参数
  37. 'args': (4, 7)
  38. },
  39. 'submit_in_fix_datetime': {
  40. 'task': 'celery_task.task_3.add3',
  41. # 比如每年的7月13日10点53分执行
  42. # 注意:默认使用utc时间,当前的时间中的小时必须要-8个小时才会到点提交
  43. 'schedule': crontab(minute=53, hour=2, day_of_month=13, month_of_year=7),
  44.  
  45. '''
  46. # 如果不想-8,可以先设置时区,再按正常时间设置
  47. app.conf.timezone = "Asia/Shanghai"
  48. app.conf.enable_utc = True
  49. '''
  50. 'args': ('Hello World',)
  51. }
  52.  
  53. }
  54.  
  55. # 上面写完后,需要起一个进程,启动计划任务
  56. # celery beat -A celery_task -l info
  57.  
  58. # 启动worker:
  59. # celery worker -A celery_task -l info -P eventlet

Django中使用celery

django-celery:由于djang-celery模块对版本的要求过于严格,而且容易出现很多bug,所以不建议使用

直接使用celery多任务结构的,将celery多任务结构的代码文件夹celery_task拷贝到Django项目中,然后在视图函数中进行任务提交、然后进行结构查看。(启动项目时候记得将worker启动起来,注意启动路径要跟你拷贝的celery_task文件同级)

注意:当我们在Django项目中使用celery,在celery的任务函数中不能直接调用django的环境(比如orm方法查询数据库),需要添加代码调用Django环境

在Python脚本中调用Django环境

  1. import os
  2. # 加载Django环境,bbs是所在的Django项目名称
  3. os.environ.setdefault("DJANGO_SETTINGS_MODULE", 'bbs.settings')
  4. # 引入Django模块
  5. import django
  6. # 初始化Django环境
  7. django.setup()
  8. # 从app当中导入models
  9. from app01 import models
  10. # 调用操作,拿到数据库中的所有Book数据对象
  11. books = models.Books.objects.all()

celery 分布式异步任务框架(celery简单使用、celery多任务结构、celery定时任务、celery计划任务、celery在Django项目中使用Python脚本调用Django环境)的更多相关文章

  1. Celery分布式异步任务框架

    一.什么是Celery Celery是一个简单.灵活且可靠的,处理大量消息的分布式系统.专注于实时处理的异步任务队列,同时也支持定时任务 二.Celery架构 1.Celery的架构由三部分组成: 消 ...

  2. celery 分布式异步队列框架使用方法

    简介: Celery  是一个python开发的异步分布式任务调度模块,是一个消息传输的中间件,可以理解为一个邮箱,每当应用程序调用celery的异步任务时,会向broker传递消息,然后celery ...

  3. celery分布式异步框架

    1.什么是Celery Celery是一个简单.灵活且可靠的,处理大量消息的分布式系统 专注于实时处理的异步任务队列 同时也支持任务调度 Celery架构 Celery的架构由三部分组成,消息中间件( ...

  4. Python开发【模块】:Celery 分布式异步消息任务队列

    Celery 前言: Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery, 举几个 ...

  5. 安装 rabbitmq ,通过生成器获取redis列表数据 与 Celery 分布式异步队列

    一.安装rabbitmq  @全体成员 超简易安装rabbitmq文档 1.安装配置epel源rpm -ivh http://dl.fedoraproject.org/pub/epel/6/i386/ ...

  6. Django项目中使用celery做异步任务

    异步任务介绍 在写项目过程中经常会遇到一些耗时的任务, 比如:发送邮件.发送短信等等~.这些操作如果都同步执行耗时长对用户体验不友好,在这种情况下就可以把任务放在后台异步执行 celery就是用于处理 ...

  7. 异步任务利器Celery(二)在django项目中使用Celery

    Celery 4.0支持django1.8及以上的版本,低于1.8的项目使用Celery 3.1. 一个django项目的组织如下: - proj/ - manage.py - proj/ - __i ...

  8. 一个Django项目中实现的简单HTML页面布局

    1 - 基础页面(被继承的模板) {% load static %} <!DOCTYPE html> <html lang="en"> <head&g ...

  9. Django配置celery执行异步任务和定时任务

    原生celery,非djcelery模块,所有演示均基于Django2.0 celery是一个基于python开发的简单.灵活且可靠的分布式任务队列框架,支持使用任务队列的方式在分布式的机器/进程/线 ...

随机推荐

  1. linux 下安装git的步骤方法

    ①.获取github最新的Git安装包下载链接,进入Linux服务器,执行下载,命令为: wget https://github.com/git/git/archive/v2.17.0.tar.gz  ...

  2. springboot与ssm的差异性

    springboot简化了ssm的配置 将外部jar包改为内部pom.xml文件配置 同时 使用了多种注解来进行注解式的开发 [图1:springboot的一些依赖模块] 通过原springmvc机制 ...

  3. 怎么把ubuntu升级到最新版本

    首先是Ctrl+Alt+T 打开终端,然后在终端中输入指令(更新资源) sudo apt-get update 接着是对软件进行升级.(这是一个漫长的过程,需要下载资源) sudo apt-get u ...

  4. P4141 消失之物

    目录 链接 思路 代码 链接 P4141 消失之物 思路 f[N];//表示删掉物品后能出现容积为i的方案数 a[N];//单纯0-1背包的方案数asd 那么就先求出a[i]来,然后转移就是 if(j ...

  5. 信息学奥赛一本通 提高篇 序列第k个数 及 快速幂

    我是传送门 这个题首先是先判断是等差还是等比数列 等差的话非常简单: 前后两个数是等差的,举个栗子: 3 6 9 12 这几个数,(我感觉 1 2 3 4并说明不了什么) 每次都加3嘛,很容易看出,第 ...

  6. PHP Record the number of login users

    Function to record how many times the user logs in Connect to the database first: you can create a n ...

  7. mpvue图片上传

    mpvue小程序项目中的图片上传 我的csdn博客地址:https://blog.csdn.net/zmkyf1993 一般我是优先更新csdn内容,然后在拷过来的. 效果图 通过mpvue文档得知他 ...

  8. vue使用案例,vue初始化,vue初始化方法,vue条件语句,vue在js里面添加元素调用vue方法

     <div id="main" > <button id='but1' type="button" v-on:click="save ...

  9. 关于redis为什么不支持回滚操作.

    redis 不支持会滚操作的说明.

  10. Apache Kylin - 大数据下的OLAP解决方案

    OLAPCube是一种典型的多维数据分析技术,Cube本身可以认为是不同维度数据组成的dataset,一个OLAP Cube 可以拥有多个维度(Dimension),以及多个事实(Factor Mea ...