Celery 收下这捆芹菜!
Celery简介
Celery是一个强大的 分布式任务队列 的 异步处理框架,它可以让任务的执行完全脱离主程序,甚至可以被分配到其他主机上运行。我们通常使用它来实现异步任务(async task)和定时任务(crontab)
Celery 官网:http://www.celeryproject.org/
Celery 官方文档英文版:http://docs.celeryproject.org/en/latest/index.html
Celery 官方文档中文版:http://docs.jinkan.org/docs/celery/
Celery构成
Task
任务模块, 包含异步任务和定时任务, 异步任务通常在业务逻辑中被触发并发往Broker任务队列, 定时任务由Celery Beat 进程周期性地发往Broker任务队列
Broker
消息中间件, 就是任务调度队列, 用来接收任务, 将任务存储到队列中, 就像是生产者与消费者模型中的队列一样
Celery本身不提供Broker, 官方推荐使用RabbitMQ和Redis
Worker
任务的执行单元, 它实时监控Broker队列, 获取队列中的任务, 并执行, 可以看做是生产者与消费者模型中的消费者
Backend
任务执行结果的存储单元, 用来存储任务结果, 以便查询
Celery本身不提供Backend, 官方推荐使用RabbitMQ和Redis
Celery使用
安装
python安装Celery: pip install celery
我们使用Redis作为Broker和Backend, 因此确保你的设备配置了Redis环境
基本使用
"""
project
├── celery_task # celery包
│ ├── __init__.py # 包文件
│ ├── celery.py # celery连接和配置相关文件,且名字必须是celery.py
│ └── tasks.py # 所有任务函数
├── add_task.py # 添加任务
└── get_result.py # 获取结果
"""
异步任务: delay
"""
1.执行add_task.py将任务添加到队列
2.cmd切换至所在文件目录celery_task下运行worker:
>: celery worker -A celery_task -l info -P eventlet
3.执行get_result.py获取任务结果
"""
# celery.py
from celery import Celery
# 配置消息中间件, 用来接收任务
broker = 'redis://127.0.0.1:6379/0'
# 配置backend, 用来存储任务执行结果
backend = 'redis://127.0.0.1:6379/1'
# worker, 任务执行单元
app = Celery(broker=broker, backend=backend)
# tasks.py
from .celery import app
# 定义任务
@app.task
def add(x, y):
res = x + y
print(f'{x}+{y}={res}')
return res
@app.task
def minus(x, y):
res = x - y
print(f'{x}-{y}={res}')
return res
# add_task.py
from .tasks import add, minus
# 在业务逻辑中触发异步任务
add_results = add.delay(10, 20)
# 任务执行结果的id
print(add_results.id)
# get_result.py
from .celery import app
from .add_tasks import add_results
from celery.result import AsyncResult
if __name__ == '__main__':
# 获取异步任务结果对象, 参数:id, app
async = AsyncResult(id=add_results.id, app=app)
if async.successful():
result = async.get()
print('任务执行成功')
print(result)
elif async.failed():
print('任务失败')
elif async.status == 'PENDING':
print('任务等待中被执行')
elif async.status == 'RETRY':
print('任务异常后正在重试')
elif async.status == 'STARTED':
print('任务已经开始被执行')
延迟任务: apply_async
from celery_task.tasks import add
from datetime import timedelta, datetime
# 添加延时任务, 10秒后执行
add_results = add.apply_async(args=(10, 20), eta=datetime.utcnow() + timedelta(seconds=10))
# 任务执行结果的id
print(add_results.id)
周期任务: beat_schedule
注意: 周期任务是通过 celery beat
来周期性添加的, , 因此启动worker服务之后, 还要重开一个cmd窗口启动beat服务: celery beat -A celery_task -l info
# celery.py
from celery import Celery
from datetime import timedelta
from celery.schedules import crontab
# 配置消息中间件, 用来接收任务
broker = 'redis://127.0.0.1:6379/0'
# 配置backend, 用来存储任务执行结果
backend = 'redis://127.0.0.1:6379/1'
# worker, 任务执行单元
app = Celery(broker=broker, backend=backend, include=['celery_task.tasks'])
# 时区
app.conf.timezone = 'Asia/Shanghai'
app.conf.enable_utc = False
app.conf.beat_schedule = {
'add-task': {
'task': 'celery_task.tasks.add',
# 每10秒添加一次任务
'schedule': timedelta(seconds=10),
'args': (10, 20)
},
'minus-task': {
'task': 'celery_task.tasks.minus',
# 每周一八点半添加一次任务
'schedule': crontab(hour=8, minute=30, day_of_week=1),
'args': (20, 10)
}
}
Django配置Celery
在根目录下创建包文件夹 celery_task
"""
project
├── celery_task # celery包
├── __init__.py # 包文件
├── celery.py # celery连接和配置相关文件,且名字必须是celery.py
└── tasks.py # 所有任务函数
"""
celery.py
# 1.加载Django配置环境
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", 'luffyapi.settings.dev')
# 2.加载Celery配置环境
from celery import Celery
broker = 'redis://127.0.0.1:6379/0'
backend = 'redis://127.0.0.1:6379/1'
app = Celery(broker=broker, backend=backend, include=['celery_task.tasks.py'])
# 时区
app.conf.timezone = 'Asia/Shanghai'
# UTC
app.conf.enable_utc = False
from datetime import timedelta
app.conf.beat_schedules = {
'update-banner-cache': {
'task': 'celery_task.tasks.py.update_banner_cache',
# 每10秒添加一次
'schedule': timedelta(seconds=10),
'args': ()
}
}
task.py
from .celery import app
from home.models import Banner
from home.serializers import BannerModerSerializer
from django.conf import settings
from django.core.cache import cache
@app.task
def update_banner_cache():
print('lalal')
banner_query = Banner.objects.filter(is_delete=False, is_show=True).order_by('-order').all()
serializer_obj = BannerModerSerializer(data=banner_query, many=True)
banner_data = serializer_obj.data
for banner in banner_data:
banner['image'] = settings.BASE_URL + banner.get('image')
cache.set('banner_cache', banner_data)
return True
Celery 收下这捆芹菜!的更多相关文章
- 毕业季offer怎么拿?收下这份非典型求职面试指南
摘要:求职面试莫慌,先自我评估一下 ,华为云专家手把手为你指导. 本文分享自华为云社区<毕业季offer怎么拿?收下这份非典型求职面试指南>,原文作者:技术火炬手 . 又是一年毕业季,对于 ...
- Java开发者必备的10大学习网站,送给入门学习java的你,请收下!
作为开发者来说,必备的除了对编码的热情还要有自己的一套技巧,另外不可缺少的就是平时学习的网站.以下本人收集的 Java 开发者必备的网站,这些网站可以提供信息.以及一些很棒的讲座 , 还能解答一般问题 ...
- java枚举使用详解,整理的很好,只能收下。。。
java枚举使用详解 在实际编程中,往往存在着这样的“数据集”,它们的数值在程序中是稳定的,而且“数据集”中的元素是有限的. 例如星期一到星期日七个数据元素组成了一周的“数据集”,春夏秋冬四个数据元素 ...
- 301重定向方法大全及SEO中网址规范化,看着不错先收下
301重定向方法大全及SEO中网址规范化 现在大多数网站都存在一些内容相同但网址(URL)不一样的重复内容,这些重复的内容对于搜索引擎来说却可能被认为是复制网页,复制网页虽然不会被惩罚但因多个网址存在 ...
- 这份Koa的简易Router手敲指南请收下
上一期链接--也就是本文的基础,参考KOA,5步手写一款粗糙的web框架 本文参考仓库:点我 Router其实就是路径匹配,通过匹配路径,返回给用户相应的网站内容. 以下方例子为例,主要通过提取req ...
- JAVA工程师必学技能,进阶&涨薪的推进器!这份实战教程请收下
Netty 作为互联网中间件的基石,是 JAVA 工程师进阶为高级程序员必备的能力之一.也是目前是互联网中间件领域使用最广泛最核心的网络通信框架. Netty是一个高性能.异步事件驱动的NIO框架,它 ...
- Python的22个编程技巧,请收下!
1. 原地交换两个数字 Python 提供了一个直观的在一行代码中赋值与交换(变量值)的方法,请参见下面的示例: x,y= 10,20 print(x,y) x,y= y,x print(x,y) # ...
- 前端面试?这份手撸Promise请你收下
前言 现在很多大厂面试前端都会要求能够手动的写出一个Promise,所以这里整理了一份手写的Promise. 绝对详细,功能绝对强大.如果你不了解Promise的基本使用,那么本篇文章可能不太适合你, ...
- 收下这款 Vue 项目模版,它将让你的开发效率在 2021 年提高 50%
这是什么 vue-automation 是一款开箱即用的 Vue 项目模版,它基于 Vue CLI 4 众所周知,虽然 Vue CLI 提供了脚手架的功能,但由于官方的脚手架过于简单,运用在实际项目开 ...
随机推荐
- 【知识小结】Git 个人学习笔记及心得
https://mp.weixin.qq.com/s/D96dXYfu3XAA4ac456qo0g git架构 工作区:就是你在电脑里能看到的目录. 版本库:工作区有一个隐藏目录.git,,而是Git ...
- IntStack(存放int型值,带迭代器) 附模板化实现 p406
1 该栈只用于存在int型数据 #include "../require.h" #include <iostream> using namespace std; cla ...
- java 集合之HashMap的三种遍历
HashMap 是一个散列表,它存储的内容是键值对(key-value)映射. 这周我们只需记住三种遍历方法 1.通过keySet()获取键,再利用hashmap里面的.get(key)方法通过键获取 ...
- vue调用兄弟组件的方法使用vueBus调用$emit、$on(只需触发方法即可,不需要考虑传值或参数的问题)
触发方: vueBus.$emit('queryAll') 被触发方: created() { vueBus.$on('queryAll', () => { this.getList() // ...
- WPF 解决弹出模态窗口关闭后,主窗口不在最前
本文告诉大家如何解决这个问题,在 WPF 的软件,弹出一个模态窗口.使用另一个窗口在模态窗口前面.从任务栏打开模态窗口.关闭模态窗口.这时发现,主窗口会在刚才使用的另一个窗口下面 这是 Windows ...
- Eclipse修改控制台字体
步骤:Window-->Preference-->General-->Appearance-->Colors and Fonts-->Basic-->Text Fo ...
- vue中处理时间格式化的问题
vue main.js中修改Date原型链,插入(百度) Date.prototype.format = function(fmt) { var o = { "M+" : this ...
- 编写jQuery插件的方法和注意点
编写jQuery插件的方法和注意点 插件的种类 jQuery的插件主要分为3种类型. 1. 封装对象方法的插件 这种插件是将对象方法封装起来,用于对通过选择器获取的jQuery对象进行操作,是最常见的 ...
- ES安装&常见错误
ES常见错误 案例一 [2018-06-20T02:35:47,152][INFO ][o.e.b.BootstrapChecks ] [SUcoFrg] bound or publishing to ...
- boostrap-非常好用但是容易让人忽略的地方【3】:clearfix
代码 显示结果 代码 结果