牛哄哄的celery
一、什么是Celery
1.1、celery是什么
Celery是一个简单、灵活且可靠的,处理大量消息的分布式系统,专注于实时处理的异步任务队列,同时也支持任务调度。

Celery的架构由三部分组成,消息中间件(message broker),任务执行单元(worker)和任务执行结果存储(task result store)组成。
消息中间件
Celery本身不提供消息服务,但是可以方便的和第三方提供的消息中间件集成。包括,RabbitMQ, Redis等等
任务执行单元
Worker是Celery提供的任务执行的单元,worker并发的运行在分布式的系统节点中。
任务结果存储
Task result store用来存储Worker执行的任务的结果,Celery支持以不同方式存储任务的结果,包括AMQP, redis等
另外, Celery还支持不同的并发和序列化的手段
- 并发:Prefork, Eventlet, gevent, threads/single threaded
- 序列化:pickle, json, yaml, msgpack. zlib, bzip2 compression, Cryptographic message signing 等等
1.2、使用场景
celery是一个强大的 分布式任务队列的异步处理框架,它可以让任务的执行完全脱离主程序,甚至可以被分配到其他主机上运行。我们通常使用它来实现异步任务(async task)和定时任务(crontab)。
异步任务:将耗时操作任务提交给Celery去异步执行,比如发送短信/邮件、消息推送、音视频处理等等
定时任务:定时执行某件事情,比如每天数据统计
1.3、Celery具有以下优点
Simple(简单)
Celery 使用和维护都非常简单,并且不需要配置文件。 Highly Available(高可用)
woker和client会在网络连接丢失或者失败时,自动进行重试。并且有的brokers 也支持“双主”或者“主/从”的方式实现高可用。 Fast(快速)
单个的Celery进程每分钟可以处理百万级的任务,并且只需要毫秒级的往返延迟(使用 RabbitMQ, librabbitmq, 和优化设置时) Flexible(灵活)
Celery几乎每个部分都可以扩展使用,自定义池实现、序列化、压缩方案、日志记录、调度器、消费者、生产者、broker传输等等。
1.4、Celery安装
你可以安装Celery通过Python包管理平台(PyPI)或者源码安装
使用pip安装:
$ pip install -U Celery
或着:
$ sudo easy_install Celery
二、Celery执行异步任务
2.1、基本使用
创建项目celerypro
创建异步任务执行文件celery_task:
import celery
import time
backend='redis://127.0.0.1:6379/1'
broker='redis://127.0.0.1:6379/2'
cel=celery.Celery('test',backend=backend,broker=broker)
@cel.task
def send_email(name):
print("向%s发送邮件..."%name)
time.sleep(5)
print("向%s发送邮件完成"%name)
return "ok"
创建执行任务文件,produce_task.py:
from celery_task import send_email
result = send_email.delay("yuan")
print(result.id)
result2 = send_email.delay("alex")
print(result2.id)
注意,异步任务文件命令执行:
celery worker -A celery_app_task -l info
创建py文件:result.py,查看任务执行结果,
from celery.result import AsyncResult
from celery_task import cel async_result=AsyncResult(id="c6ddd5b7-a662-4f0e-93d4-ab69ec2aea5d", app=cel) if async_result.successful():
result = async_result.get()
print(result)
# result.forget() # 将结果删除
elif async_result.failed():
print('执行失败')
elif async_result.status == 'PENDING':
print('任务等待中被执行')
elif async_result.status == 'RETRY':
print('任务异常后正在重试')
elif async_result.status == 'STARTED':
print('任务已经开始被执行')
2.1、多任务结构

celery.py:
from celery import Celery
cel = Celery('celery_demo',
broker='redis://127.0.0.1:6379/1',
backend='redis://127.0.0.1:6379/2',
# 包含以下两个任务文件,去相应的py文件中找任务,对多个任务做分类
include=['celery_tasks.task01',
'celery_tasks.task02'
])
# 时区
cel.conf.timezone = 'Asia/Shanghai'
# 是否使用UTC
cel.conf.enable_utc = False
task01.py,task02.py:
#task01
import time
from celery_tasks.celery import cel @cel.task
def send_email(res):
time.sleep(5)
return "完成向%s发送邮件任务"%res #task02
import time
from celery_tasks.celery import cel
@cel.task
def send_msg(name):
time.sleep(5)
return "完成向%s发送短信任务"%name
produce_task.py:
from celery_tasks.task01 import send_email
from celery_tasks.task02 import send_msg # 立即告知celery去执行test_celery任务,并传入一个参数
result = send_email.delay('yuan')
print(result.id)
result = send_msg.delay('yuan')
print(result.id)
check_result.py:
from celery.result import AsyncResult
from celery_tasks.celery import cel async_result = AsyncResult(id="562834c6-e4be-46d2-908a-b102adbbf390", app=cel) if async_result.successful():
result = async_result.get()
print(result)
# result.forget() # 将结果删除,执行完成,结果不会自动删除
# async.revoke(terminate=True) # 无论现在是什么时候,都要终止
# async.revoke(terminate=False) # 如果任务还没有开始执行呢,那么就可以终止。
elif async_result.failed():
print('执行失败')
elif async_result.status == 'PENDING':
print('任务等待中被执行')
elif async_result.status == 'RETRY':
print('任务异常后正在重试')
elif async_result.status == 'STARTED':
print('任务已经开始被执行')
开启work:celery worker -A celery_task -l info -P eventlet,添加任务(执行produce_task.py),检查任务执行结果(执行check_result.py)
三、Celery执行定时任务
设定时间让celery执行一个定时任务,produce_task.py:
from celery_task import send_email
from datetime import datetime # 方式一
# v1 = datetime(2020, 3, 11, 16, 19, 00)
# print(v1)
# v2 = datetime.utcfromtimestamp(v1.timestamp())
# print(v2)
# result = send_email.apply_async(args=["egon",], eta=v2)
# print(result.id) # 方式二
ctime = datetime.now()
# 默认用utc时间
utc_ctime = datetime.utcfromtimestamp(ctime.timestamp())
from datetime import timedelta
time_delay = timedelta(seconds=10)
task_time = utc_ctime + time_delay # 使用apply_async并设定时间
result = send_email.apply_async(args=["egon"], eta=task_time)
print(result.id)
多任务结构中celery.py修改如下:
from datetime import timedelta
from celery import Celery
from celery.schedules import crontab cel = Celery('tasks', broker='redis://127.0.0.1:6379/1', backend='redis://127.0.0.1:6379/2', include=[
'celery_tasks.task01',
'celery_tasks.task02',
])
cel.conf.timezone = 'Asia/Shanghai'
cel.conf.enable_utc = False cel.conf.beat_schedule = {
# 名字随意命名
'add-every-10-seconds': {
# 执行tasks1下的test_celery函数
'task': 'celery_tasks.task01.send_email',
# 每隔2秒执行一次
# 'schedule': 1.0,
# 'schedule': crontab(minute="*/1"),
'schedule': timedelta(seconds=6),
# 传递参数
'args': ('张三',)
},
# 'add-every-12-seconds': {
# 'task': 'celery_tasks.task01.send_email',
# 每年4月11号,8点42分执行
# 'schedule': crontab(minute=42, hour=8, day_of_month=11, month_of_year=4),
# 'args': ('张三',)
# },
}
# 启动 Beat 程序$ celery beat -A proj
# Celery Beat进程会读取配置文件的内容,周期性的将配置中到期需要执行的任务发送给任务队列 # 之后启动 worker 进程.$ celery -A proj worker -l info 或者$ celery -B -A proj worker -l info
四、Django中使用celery
项目根目录创建celery包,目录结构如下:
mycelery/
├── config.py
├── __init__.py
├── main.py
└── sms/
├── __init__.py
├── tasks.py
配置文件config.py:
broker_url = 'redis://127.0.0.1:6379/15'
result_backend = 'redis://127.0.0.1:6379/14'
任务文件tasks.py:
# celery的任务必须写在tasks.py的文件中,别的文件名称不识别!!!
from mycelerys.main import app
import time import logging
log = logging.getLogger("django") @app.task # name表示设置任务的名称,如果不填写,则默认使用函数名做为任务名
def send_sms(mobile):
"""发送短信"""
print("向手机号%s发送短信成功!"%mobile)
time.sleep(5) return "send_sms OK" @app.task # name表示设置任务的名称,如果不填写,则默认使用函数名做为任务名
def send_sms2(mobile):
print("向手机号%s发送短信成功!" % mobile)
time.sleep(5) return "send_sms2 OK"
最后在main.py主程序中对django的配置文件进行加载
# 主程序
import os
from celery import Celery
# 创建celery实例对象
app = Celery("sms") # 把celery和django进行组合,识别和加载django的配置文件
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'celeryPros.settings.dev') # 通过app对象加载配置
app.config_from_object("mycelerys.config") # 加载任务
# 参数必须必须是一个列表,里面的每一个任务都是任务的路径名称
# app.autodiscover_tasks(["任务1","任务2"])
app.autodiscover_tasks(["mycelerys.sms",]) # 启动Celery的命令
# 强烈建议切换目录到mycelery根目录下启动
# celery -A mycelery.main worker --loglevel=info
Django视图调用:
from django.shortcuts import render # Create your views here. from django.shortcuts import render,HttpResponse
from mycelerys.sms.tasks import send_sms,send_sms2
from datetime import timedelta from datetime import datetime
def test(request): ################################# 异步任务 # 1. 声明一个和celery一模一样的任务函数,但是我们可以导包来解决 # send_sms.delay("110")
# send_sms2.delay("119")
# send_sms.delay() 如果调用的任务函数没有参数,则不需要填写任何内容 ################################# 定时任务 # ctime = datetime.now()
# # 默认用utc时间
# utc_ctime = datetime.utcfromtimestamp(ctime.timestamp())
# time_delay = timedelta(seconds=10)
# task_time = utc_ctime + time_delay
# result = send_sms.apply_async(["911", ], eta=task_time)
# print(result.id) return HttpResponse('ok')
牛哄哄的celery的更多相关文章
- 一些牛逼哄哄的javascript面试题
今天我们来对这5个题目详细分析一下,希望对大家有所帮助. 注: 问题来自大名鼎鼎的前端架构师Baranovskiy的帖子<So, you think you know JavaScript?&g ...
- 牛逼哄哄的Qt库
目录 一.有价值 - 好的网站 - 好的文章 二.Qt开源库-工具 - QtXlsx--excel读写库 三.Qt开源库-控件 - libqxt编译 - Qwt - QCustomPlot - 其他 ...
- 【转】tars源码漫谈第1篇------tc_loki.h (牛逼哄哄的loki库)
loki库是C++模板大牛Andrei写的, 里面大量运用模板的特性, 而tc_loki.h借用了loki库的部分代码, 形成了一个基本的文件tc_loki.h, 来看看: #ifndef __TC_ ...
- 牛逼哄哄的 Lambda 表达式,简洁优雅就是生产力!
阅读本文大概需要 4 分钟. 作者:Sevenvidia https://www.zhihu.com/question/20125256/answer/324121308 什么是Lambda? 我们知 ...
- 开发基础之牛逼哄哄的 Lambda 表达式,简洁优雅就是生产力
什么是Lambda? 我们知道,对于一个Java变量,我们可以赋给其一个“值”. 如果你想把“一块代码”赋给一个Java变量,应该怎么做呢? 比如,我想把右边那块代码,赋给一个叫做aBlockOfCo ...
- 牛逼哄洪的 Java 8 Stream,性能也牛逼么?
那么,Stream API的性能到底如何呢,代码整洁的背后是否意味着性能的损耗呢?本文对Stream API的性能一探究竟. 为保证测试结果真实可信,我们将JVM运行在 -server模式下,测试数据 ...
- 牛逼哄哄的 API 网关是什么鬼?面试必问!
Java技术栈 www.javastack.cn 优秀的Java技术公众号 作者:aCoder2013 github.com/aCoder2013/blog/issues/35 前言 假设你正在开发一 ...
- 恕我直言,牛逼哄哄的MongoDB你可能只会30%
MongoDB闪亮登场 自我介绍 MongoDB 是一个基于分布式文件存储的数据库.由 C++ 语言编写.旨在为 WEB 应用提供可扩展的高性能数据存储解决方案. MongoDB 是一个介于关系数据库 ...
- 牛逼哄哄的PageHelper分页插件到底是怎么实现的?网友:给我10分钟,给你写一个~
Hi,各位读者们 PageHelper是一款好用的开源免费的Mybatis第三方物理分页插件,其实我并不想加上好用两个字,但是为了表扬插件作者开源免费的崇高精神,我毫不犹豫的加上了好用一词作为赞美. ...
随机推荐
- 7.18 NOI模拟赛 树论 线段树 树链剖分 树的直径的中心 SG函数 换根
LINK:树论 不愧是我认识的出题人 出的题就是牛掰 == 他好像不认识我 考试的时候 只会写42 还有两个subtask写挂了 拿了37 确实两个subtask合起来只有5分的好成绩 父亲能转移到自 ...
- POJ 2443 Set Operation 题解
本文同时发布于 博客园 洛谷博客 题目链接 题目分析 给你n个集合,每个集合里面都有可能会重复的数字 q个询问,每次询问两个数是否会在同一集合内 $n<=1000$ $q<=200000$ ...
- Spring IoC是如何进行依赖注入的
依赖注入(DI) DI(Dependency Injection),Spring IoC 不是一种技术,而是一种思想,通过这种思想,能够指导我们设计出松耦合的程序代码.而Spring IoC这个思想的 ...
- Zabbix5 对接 SAML 协议 SSO
Zabbix5 对接 SAML 协议 SSO 在 Zabbix5.0 开始已经支持 SAML 认证 官文文档: https://www.zabbix.com/documentation/current ...
- 从零搭建Spring Boot脚手架(4):手写Mybatis通用Mapper
1. 前言 今天继续搭建我们的kono Spring Boot脚手架,上一文把国内最流行的ORM框架Mybatis也集成了进去.但是很多时候我们希望有一些开箱即用的通用Mapper来简化我们的开发.我 ...
- 社区观点 | 关于比原链MOV巡查官制度的几点思考
在ChainNode白皮书解密读书会01期活动中,比原链高级研究员刘秋杉带领大家领读「MOV:下一代去中心跨链 Layer 2 价值交换协议」白皮书,得到了很多粉丝的关注,其中gentledog的读书 ...
- 博客主题推荐——复杂&简单
首先感谢原作者cjunn提供的主题autm,以下配置都基于此主题设定.很多小伙伴喜欢现在的样式,分享如下.只需简单几步即可. 如果你想使用本博客主题样式,并希望能得到远程推送更新,只需查看 快速部署. ...
- JS 与 jQery 的区别主要在于 DOM
//目前正在学习前端阶段,把知识点整理.保存下来以便日后查看 首先引入jQery: 需要先引入css,再引入js: jQery需要在js前引入,再引入框架,最后才是js的引入:css也相同,先引入框架 ...
- JS学习第五天
循环语句: for(变量 in (容器名)数组名){ 执行的语句块: break: 结束整个循环; continue:结束本次循环, 进入下一次循环: } 双层for循环: 外层循环控制行,内层循环控 ...
- C#LeetCode刷题之#501-二叉搜索树中的众数(Find Mode in Binary Search Tree)
问题 该文章的最新版本已迁移至个人博客[比特飞],单击链接 https://www.byteflying.com/archives/4086 访问. 给定一个有相同值的二叉搜索树(BST),找出 BS ...