python之celery队列模块
一、celery队列简介
Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery.
1.1使用场景
1.你想对100台机器执行一条批量命令,可能会花很长时间 ,但你不想让你的程序等着结果返回,而是给你返回 一个任务ID,你过一段时间只需要拿着这个任务id就可以拿到任务执行结果, 在任务执行ing进行时,你可以继续做其它的事情。
2.你想做一个定时任务,比如每天检测一下你们所有客户的资料,如果发现今天 是客户的生日,就给他发个短信祝福
1.2celery原理
Celery 在执行任务时需要通过一个消息中间件来接收和发送任务消息,以及存储任务结果, 一般使用rabbitMQ or Redis 或者是数据库来存放消息的中间结果
Celery优点:
- 简单:一单熟悉了celery的工作流程后,配置和使用还是比较简单的
- 高可用:当任务执行失败或执行过程中发生连接中断,celery 会自动尝试重新执行任务
- 快速:一个单进程的celery每分钟可处理上百万个任务
- 灵活: 几乎celery的各个组件都可以被扩展及自定制
Celery缺点:
1.目前只能在Linux系统上有较好的支持
Celery工作流程图:
1. Celery Beat:任务调度器,Beat进程会读取配置文件的内容,周期性地将配置中到期需要执行的任务发送给任务队列。
2. Celery Worker:执行任务的消费者,通常会在多台服务器运行多个消费者来提高执行效率。
3. Broker:消息代理,或者叫作消息中间件,接受任务生产者发送过来的任务消息,存进队列再按序分发给任务消费方(通常是消息队列或者数据库)。
4. Producer:调用了Celery提供的API、函数或者装饰器而产生任务并交给任务队列处理的都是任务生产者。
5. Result Backend:任务处理完后保存状态信息和结果,以供查询。Celery默认已支持Redis、RabbitMQ、MongoDB、Django ORM、SQLAlchemy等方式。
Celery的架构图如图所示:

在传统的web应用中,Django的web页面通过url的映射到view,view再执行方法,如果方法需要调用大量的脚本,执行大量的任务,页面就会阻塞,如果在项目中使用Celery队列.首先用户的任务会被celery放到broker中进行中转,然后将任务分为一个个的task来执行,由于celery是异步机制,所以会直接给用户返回task_id,页面拿到task_id就可以执行后续的操作,比如查看任务进度,暂停任务,而无需等待所有任务全部执行完毕,才能看到页面。
二、celery安装
2.1安装:
1.在linux(ubuntu)系统上首先安装Celery队列
pip3 install Celery
2.在linux安装redis
sudo apt-get install redis-server
3.在linux上安装redis-celery中间件
pip3 install -U "celery[redis]"
4.启动redis
sudo /etc/init.d/redis-server start
三、celery使用
3.1简单使用
命名为tasks.py
from celery import Celery
app = Celery('tasks',
broker='redis://localhost',
backend='redis://localhost')
@app.task
def add(x,y):
print("running...",x,y)
return x+y
启动监听并开始执行该服务
celery -A tasks worker -l debug
在开启一个终端进行测试任务
进入python环境
from tasks import add
t = add.delay(3,3) #此时worker会生成一个任务和任务id
t.get() #获取任务执行的结果
t.get(propagate=False) #如果任务执行中出现异常,在client端不会异常退出
t.ready()#查看任务是否执行完毕
t.traceback #打印异常详细信息
3.2项目中创建celery
在当前的目录下创建文件夹celery_pro
mkdir celery_pro
在此目录下创建两个文件
目录结构:
celery_proj
/__init__.py
/celery.py
/tasks.py
celery.py(定义了celery的一些元信息)
from __future__ import absolute_import, unicode_literals
from celery import Celery app = Celery('proj',
broker='redis://localhost', #消息中间接收
backend='redis://localhost', #消息结果存放
include=['proj.tasks']) #执行任务的文件 # Optional configuration, see the application user guide.
app.conf.update(
result_expires=3600,
) if __name__ == '__main__':
app.start()
tasks.py (定义任务执行的具体逻辑和调用的具体方法)
from __future__ import absolute_import, unicode_literals
from .celery import app @app.task
def add(x, y):
return x + y @app.task
def mul(x, y):
return x * y @app.task
def xsum(numbers):
return sum(numbers)
启动worker
celery -A celery_pro worker -l debug
再另一个窗口打开python命令模式进行测试
from celery_pro import tasks t = tasks.add.delay(3,4)
t.get()
Celery的分布式:多启动worker就可以自动实现负载均衡,无需手动管理
Celery永驻后台(开启&重启&关闭)
celery multi start w1 -A celery_pro -l info #开启后台celery任务
celery multi restart w1 -A proj -l info #重启该服务
celery multi stop w1 -A proj -l info #关闭该服务
3.3 celery定时任务
在celery_pro文件夹下创建periodic_tasks.py
目录结构:
celery_proj
/__init__.py
/celery.py
/tasks.py
/periodic_tasks.py
文件内容如下:
from __future__ import absolute_import, unicode_literals
from .celery import app
from celery.schedules import crontab @app.on_after_configure.connect
def setup_periodic_tasks(sender, **kwargs):
# Calls test('hello') every 10 seconds.
sender.add_periodic_task(10.0, test.s('hello'), name='add every 10') # Calls test('world') every 30 seconds
sender.add_periodic_task(30.0, test.s('world'), expires=10) # Executes every Monday morning at 7:30 a.m.
sender.add_periodic_task(
crontab(hour=21, minute=42, day_of_week=5),
test.s('Happy Mondays!'),
) @app.task
def test(arg):
print(arg)
修改celery.py,加入periodic_task.py
from __future__ import absolute_import, unicode_literals
from celery import Celery app = Celery('proj',
broker='redis://localhost',
backend='redis://localhost',
include=['celery_pro.tasks','celery_pro.periodic_tasks']) # Optional configuration, see the application user guide.
app.conf.update(
result_expires=3600,
) if __name__ == '__main__':
app.start()
在服务端启动 celery -A celery_pro worker -l debug
在客户端启动 celery -A celery_pro.periodic_tasks beat -l debug
在服务端如果看到打印的hell ,world说明定时任务配置成功
上面是通过调用函数添加定时任务,也可以像写配置文件 一样的形式添加, 下面是每30s执行的任务
在celery.py中添加
app.conf.beat_schedule = {
'add-every-30-seconds': {
'task': 'cerely_pro.tasks.add', #执行的具体方法
'schedule': 5.5, #每秒钟执行
'args': (16, 16) #执行的具体动作的参数
},
}
app.conf.timezone = 'UTC'
更多定制
上面的定时任务比较简单,但如果你想要每周一三五的早上8点给你发邮件怎么办呢?用crontab功能,跟linux自带的crontab功能是一样的,可以个性化定制任务执行时间
rom celery.schedules import crontab
app.conf.beat_schedule = {
#在每周一早上7:30执行
'add-every-monday-morning': {
'task': 'celery_pro.tasks.add',
'schedule': crontab(hour=7, minute=30, day_of_week=1),
'args': (16, 16),
},
还有更多定时配置方式如下:
| Example | Meaning |
crontab() |
Execute every minute. |
crontab(minute=0, hour=0) |
Execute daily at midnight. |
crontab(minute=0, hour='*/3') |
Execute every three hours: midnight, 3am, 6am, 9am, noon, 3pm, 6pm, 9pm. |
|
Same as previous. |
crontab(minute='*/15') |
Execute every 15 minutes. |
crontab(day_of_week='sunday') |
Execute every minute (!) at Sundays. |
|
Same as previous. |
|
Execute every ten minutes, but only between 3-4 am, 5-6 pm, and 10-11 pm on Thursdays or Fridays. |
crontab(minute=0,hour='*/2,*/3') |
Execute every even hour, and every hour divisible by three. This means: at every hour except: 1am, 5am, 7am, 11am, 1pm, 5pm, 7pm, 11pm |
crontab(minute=0, hour='*/5') |
Execute hour divisible by 5. This means that it is triggered at 3pm, not 5pm (since 3pm equals the 24-hour clock value of “15”, which is divisible by 5). |
crontab(minute=0, hour='*/3,8-17') |
Execute every hour divisible by 3, and every hour during office hours (8am-5pm). |
crontab(0, 0,day_of_month='2') |
Execute on the second day of every month. |
|
Execute on every even numbered day. |
|
Execute on the first and third weeks of the month. |
|
Execute on the eleventh of May every year. |
|
Execute on the first month of every quarter. |
3.4Celery+Django实现异步任务分发
1.在setting.py的文件同一级别创建celery.py
from __future__ import absolute_import, unicode_literals
import os
from celery import Celery # 设置Django的环境变量
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'PerfectCRM.settings') #设置app的默认处理方式,如果不设置默认是rabbitMQ
app = Celery('proj',
broker='redis://localhost',
backend='redis://localhost'
) #配置前缀
app.config_from_object('django.conf:settings', namespace='CELERY') #自动扫描app下的tasks文件
app.autodiscover_tasks() @app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))
2.修改当前目录下的__init__文件
from __future__ import absolute_import, unicode_literals #启动时检测celery文件
from .celery import app as celery_app __all__ = ['celery_app']
3.在app下新增tasks文件,写要执行的任务
from __future__ import absolute_import, unicode_literals
from celery import shared_task @shared_task
def add(x, y):
return x + y @shared_task
def mul(x, y):
return x * y @shared_task
def xsum(numbers):
return sum(numbers)
4.在另一个app下新增tasks文件
from __future__ import absolute_import, unicode_literals
from celery import shared_task
import time,random @shared_task
def randnum(start, end):
time.sleep(3)
return random.ranint(start,end)
5.在views下增加处理逻辑
from crm import tasks
from celery.result import AsyncResult
import random
#计算结果
def celery_call(request):
randnum =random.randint(0,1000)
t = tasks.add.delay(randnum,6)
print('randum',randnum)
return HttpResponse(t.id) #获取结果
def celery_result(request):
task_id = request.GET.get('id')
res = AsyncResult(id=task_id)
if res.ready():
return HttpResponse(res.get())
else:
return HttpResponse(res.ready())
6.测试
首先启动Django,从web端输入url调用celery_call方法
例:http://192.168.17.133:9000/crm/celery_call,此方法会返回一个task_id(41177118-3647-4830-b8c8-7be76d9819d7)
带着这个task_id 访问http://192.168.17.133:9000/crm/celery_result?id=41177118-3647-4830-b8c8-7be76d9819d7如果可以看到结果说明配置成功
Dnango+Celery实现定时任务
- 安装Django,Celery中间件
pip3 install django-celery-beat
- 在Django的settings文件中,新增app,名称如下
INSTALLED_APPS = (
.....,
'django_celery_beat', #新增的app
)
- 输入命令
python manage.py migrate #创建与Django有关定时计划任务的新表
- 通过celery beat开启定时任务
celery -A PrefectCRM beat -l info -S django
- 启动Django服务,进入admin配置页面
python3 manager.py runserver 0.0.0.0:9000
并设置settings.py中的
ALLOW_HOSTS=['*']
- 可以在原有业务表的基础之上看到新的三张表

后记:经测试,每添加或修改一个任务,celery beat都需要重启一次,要不然新的配置不会被celery beat进程读到
python之celery队列模块的更多相关文章
- Python Celery队列
Celery队列简介: Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery. 使用 ...
- Python第十五天 datetime模块 time模块 thread模块 threading模块 Queue队列模块 multiprocessing模块 paramiko模块 fabric模块
Python第十五天 datetime模块 time模块 thread模块 threading模块 Queue队列模块 multiprocessing模块 paramiko模块 fab ...
- 【Python】Celery异步处理
参考:http://www.cnblogs.com/znicy/p/5626040.html 参考:http://www.weiguda.com/blog/73/ 参考:http://blog.csd ...
- python之celery的使用(一)
前段时间需要使用rabbitmq做写缓存,一直使用pika+rabbitmq的组合,pika这个模块虽然可以很直观地操作rabbitmq,但是官方给的例子太简单,对其底层原理了解又不是很深,遇到很多坑 ...
- Python RabbitMQ消息队列
python内的队列queue 线程 queue:不同线程交互,不能夸进程 进程 queue:只能用于父进程与子进程,或者同一父进程下的多个子进程,进行交互 注:不同的两个独立进程是不能交互的. ...
- python之celery使用详解一
前段时间需要使用rabbitmq做写缓存,一直使用pika+rabbitmq的组合,pika这个模块虽然可以很直观地操作rabbitmq,但是官方给的例子太简单,对其底层原理了解又不是很深,遇到很多坑 ...
- 【理论】python使用celery异步处理请求
Flask中使用celery队列处理执行时间较长的请求. 一. 安装celery pip install celery flask redis 二. celery简介 Celery是个异步分布式任务队 ...
- 定时任务管理之python篇celery使用
一.为什么要用celery celery是一个简单.灵活.可靠的,处理大量消息的分布式系统,并且提供维护这样一个系统的必须工具.他是一个专注于实时处理的任务队列,同时也支持任务调度. celery是异 ...
- python之消息队列
引言 你是否遇到过两个(多个)系统间需要通过定时任务来同步某些数据?你是否在为异构系统的不同进程间相互调用.通讯的问题而苦恼.挣扎?如果是,那么恭喜你,消息服务让你可以很轻松地解决这些问题.消息服务擅 ...
随机推荐
- 使用鼠标监听器,使鼠标悬停在JTable某行时背景色改变
一.需要知道的事实: 1.当鼠标悬停在JTable上时,相应的格子(cell)的渲染器(TableCellRenderer)的渲染方法(getTableCellRenererComponent)会被调 ...
- C#导出Excel按照指定格式设置单元格属性值
最近项目中一直在写XML.Table.Excel之间的转化.之前一直都是不考虑格式的导出,今天给出一个格式,让按照格式导出,还真把我这新手为难了一翻,网上给出的资料基本一样.为了一个单元格文字变色纠结 ...
- Android开发之--常用颜色值
<?xml version="1.0" encoding="utf-8" ?> <resources> <color name=& ...
- Python 循环退出
常用语句: break :退出整个循环,循环外的语句继续执行continue :退出本次循环,继续下一次循环pass :什么也不做,相当于在这里占个位置,以便以后修改代码sys.exit() :直接退 ...
- 让nginx支持.htaccess文件实现伪静态的方法!
搞了个VPS,装了个LNMP一键安装包,然后搞了个程序放上,想实现伪静态,但是lnmp的默认规则里没有河蟹男需要的伪静态文件,得自己配置, 以前只在.htaccess里搞下就行,现在换Linux下ng ...
- 如何使用微信小程序制作banner轮播图?
在前端工程师的工作中,banner是必不可少的,那缺少了DOM的小程序是如何实现banner图的呢?如同其他的框架封装了不同的banner图的方法,小程序也封装了banner的方法,来让我一一道来: ...
- PHP(Mysqli和PDO)预处理
PHP预处理主要是用来防SQL注入的,开发程序的都明白这样一个道理,不能相信用户的任何输入,如果用户输入问题你没有做相应的安全, 那么:你的程序是很危险的,很容易被攻击的!预处理:只分析两个:mysq ...
- BNU4204:动物PK
稀奇稀奇真稀奇,动物园摆出了擂台赛.小动物们纷纷上台比试,谁能获得最后的冠军呢? 动物园长发现小动物们打擂只与自身的三项属性有关:血量,攻击力和防御力.此外,小动物在赛前都为自己准备了一系列的攻击计划 ...
- MQTT的学习研究(二)moquette-mqtt 的使用之mqtt broker的启动
在MQTT 官网 (http://mqtt.org/software)中有众多MQTT的实现方式.具体参看官网,Moquette是基于Apache Mina 的模型的一个Java MQTT broke ...
- FileInputStream与FileOutputStream类 Reader类和Writer类 解析
FileInputStream和FileOutputStream类分别用来创建磁盘文件的输入流和输出流对象,通过它们的构造函数来指定文件路径和文件名. 创建FileInputStream实例对象时,指 ...