celery rabbit mq 详解
Celery介绍和基本使用
Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery, 举几个实例场景中可用的例子:
1)你想对100台机器执行一条批量命令,可能会花很长时间 ,但你不想让你的程序等着结果返回,而是给你返回 一个任务ID,你过一段时间只需要拿着这个任务id就可以拿到任务执行结果, 在任务执行ing进行时,你可以继续做其它的事情。
2)你想做一个定时任务,比如每天检测一下你们所有客户的资料,如果发现今天 是客户的生日,就给他发个短信祝福
Celery 在执行任务时需要通过一个消息中间件来接收和发送任务消息,以及存储任务结果, 一般使用rabbitMQ or Redis,后面会讲
1.1 Celery有以下优点:
- 简单:一单熟悉了celery的工作流程后,配置和使用还是比较简单的
- 高可用:当任务执行失败或执行过程中发生连接中断,celery 会自动尝试重新执行任务
- 快速:一个单进程的celery每分钟可处理上百万个任务
- 灵活: 几乎celery的各个组件都可以被扩展及自定制

- Celery包含如下组件:
- Celery Beat:任务调度器,Beat进程会读取配置文件的内容周期性地将配置中到期需要执行的任务发送给任务队列。
- Celery Worker:执行任务的消费者,通常会在多台服务器运行多个消费者来提高执行效率。
- Broker:消息代理,或者叫做消息中间件,接受任务生产者发送过来的任务消息,存进队列再按序分发给任务消费方(通常是消息队列或者数据库)。
- Producer:调用Celery提供的API、函数或者装饰器而产生任务并交给任务队列处理的都是任务生产者。
- Result Backend:任务处理完后保存状态信息和结果,以供查询。celery默认已支持Redis、RabbitMQ、MongoDB、Django ORM、SQLAlchemy等方式。

执行依靠
celery call 发送任务给这个 -->celery组件--->发送给rabbitmq,交给---->worker1|worker2
- 环境的部署
安装celery模块:pip install celery
基础代码worker端
from celery import Celery
app = Celery('tasks',broker='redis://:alex3714@192.168.14.52') #‘tasks’给app起的名字
backend='redis://alex3714@localhost')#将结果写入到哪 @app.task
def add(x,y):
print("running...",x,y)
return x+y @app.task
def cmd(cmd_str):
print('running cmd',cmd_str)
执行这个脚本: celery -A celery_test -l debug #当执行完这条命令后就会进入监听状态
#celery_test不用写后缀名, 指定模式。
调度端执行,会形成异步执行
from celery_test import add,cmd
add(4,5) #这么执行的话只是本地显示结果。
add.delay(45,2) #让worker端执行
t1 = add.delay(45,2)当你赋值的时候worker端还会在执行一次
t1.get() #获取执行的结果
celery -A celery_test worker -l info #在开一个客户端。
#这次我们测试这个任务是怎么分发的。
t2 = add.delay(22,44)
t2 = add.delay(22,44)
t2 = add.delay(22,44)
t2 = add.delay(22,44)
#当你执行的很快的时候你会发现这个任务和rabbit MQ一样是抢任务的。 from celery import Celery
app = Celery('tasks',broker='redis://:alex3714@192.168.14.52') #‘tasks’给app起的名字
backend='redis://alex3714@localhost')#将结果写入到哪 @app.task
def add(x,y):
print("running...",x,y)
return x+y @app.task
def cmd(cmd_str):
print('running cmd',cmd_str)
time.sleep(10)
return time.time()
调度端
from celery_test import add,cmd
t1 = cmd.delay('dsfsdf')
t1.get() #这时你会发现程序是阻塞的,并没有实现异步的效果
#当然这个解决也是非常简单的
t1.get(timeout=1,propa) #这时你会发现提示你任务没有完成
t1.ready() #可以查看任务没有没有完成,返回布尔值的状态
基础测试代码celery_test.py测试端:
from celery import Celery
app = Celery('proj',include=['proj.tasks']) #app是Celery类的实例,创建的时候添加了proj.tasks这个模块,也就是包含了proj/tasks.py这个文件。
app.config_from_object('proj.celeryconfig')把Celery配置存放进proj/celeryconfig.py文件,使用app.config_from_object加载配置。
if __name__ == '__main__'
app.start()
存放任务函数的文件tasks.py
from __future__ import absolute_import
from proj.celery import app @app.task #让这个任务生效的装饰器
def add(x, y):
return x + y
配置文件celeryconfig.py
BROKER_URL = 'amqp://dongwm:123456@localhost:5672/web_develop' # 使用RabbitMQ作为消息代理 CELERY_RESULT_BACKEND = 'redis://localhost:6379/0' # 把任务结果存在了Redis CELERY_TASK_SERIALIZER = 'msgpack' # 任务序列化和反序列化使用msgpack方案 CELERY_RESULT_SERIALIZER = 'json' # 读取任务结果一般性能要求不高,所以使用了可读性更好的JSON CELERY_TASK_RESULT_EXPIRES = 60 * 60 * 24 # 任务过期时间,不建议直接写86400,应该让这样的magic数字表述更明显 CELERY_ACCEPT_CONTENT = ['json', 'msgpack'] # 指定接受的内容类型
启动上面的代码 celery -A celery_test -l info #-A指定人物名,不需要后缀,-l指定模式
开启另外一个终端,用IPython调用add函数:
from celery_test import add
r = add.delay(1,3) #在任务端执行一次
r #执行第二次
r.result #返回结果
r.status #返回状态
r.successful() #去执行结果
r.backend #保存到redis中 通过IPython触发的任务就完成了。任务的结果都需要根据上面提到的task_id获得,我们还可以用如下两种方式随时找到这个结果: task_id = '93288a00-94ee-4727-b815-53dc3474cf3f' In : add.AsyncResult(task_id).get() Out: 4 或者: In : from celery.result import AsyncResult In : AsyncResult(task_id).get() Out: 4
指定队列
Celery非常容易设置和运行,通常它会使用默认的名为celery的队列(可以通过CELERY_DEFAULT_QUEUE修改)用来存放任务。我们可以使用优先级不同的队列来确保高优先级的任务不需要等待就得到响应。
基于proj目录下的源码,我们创建一个projq目录,并对projq/celeryconfig.py添加如下配置:
from kombu import Queue
CELERY_QUEUES = ( # 定义任务队列
Queue('default', routing_key='task.#'), # 路由键以“task.”开头的消息都进default队列
Queue('web_tasks', routing_key='web.#'), # 路由键以“web.”开头的消息都进web_tasks队列
)
CELERY_DEFAULT_EXCHANGE = 'tasks' # 默认的交换机名字为tasks
CELERY_DEFAULT_EXCHANGE_TYPE = 'topic' # 默认的交换类型是topic
CELERY_DEFAULT_ROUTING_KEY = 'task.default' # 默认的路由键是task.default,这个路由键符合上面的default队列
CELERY_ROUTES = {
'projq.test.add': { # tasks.add的消息会进入web_tasks队列
'queue': 'web_tasks',
'routing_key': 'web.add',
}
}
现在用指定队列的方式启动消费者进程:
celery -A projq worker -Q web_tasks -l info
上述worker只会执行web_tasks中的任务,我们可以合理安排消费者数量,让web_tasks中任务的优先级更高。
使用任务调度
之前的例子都是由发布者触发的,本节展示一下使用Celery的Beat进程自动生成任务。基于proj目录下的源码,创建一个projb目录,对projb/celeryconfig.py添加如下配置:
CELERYBEAT_SCHEDULE = {
'add': {
'task': 'celery_test.add',
'schedule': timedelta(seconds=10), #每10秒执行一次
'args': (16, 16) #执行的参数是
}
}
启动Beat程序:
celery beat -A projb
然后启动Worker进程:
celery -A projb worker -l info
之后可以看到每10秒都会自动执行一次tasks.add。
注:Beat和Worker进程可以一并启动:
celery -B -A projb worker -l info
使用Django可以通过django-celery实现在管理后台创建、删除、更新任务,是因为它使用了自定义的调度类djcelery.schedulers.DatabaseScheduler,我们可以参考它实现Flask或者其他Web框架的管理后台来完成同样的功能。使用自定义调度类还可以实现动态添加任务。
任务绑定、记录日志和重试
任务绑定、记录日志和重试是Celery常用的3个高级属性。现在修改proj/tasks.py文件,添加div函数用于演示:
from celery.utils.log import get_task_logger
logger = get_task_logger(__name__)
@app.task(bind=True)
def div(self, x, y):
logger.info(('Executing task id {0.id}, args: {0.args!r} '
'kwargs: {0.kwargs!r}').format(self.request))
try:
result = x / y
except ZeroDivisionError as e:
raise self.retry(exc=e, countdown=5, max_retries=3)
return result
当使用bind = True后,函数的参数发生变化,多出了参数self(第一个参数),相当于把div变成了一个已绑定的方法,通过self可以获得任务的上下文。
在IPython中调用div:
from proj.tasks import div
r = div.delay(2, 1)
[2017-09-20 15:50:31,853: INFO/Worker-1] proj.tasks.div[1da82fb8-20de-4d5a-9b48-045da6db0cda]: Executing task id 1da82fb8-20de-4d5a-9b48-045da6db0cda, args: [2, 1] kwargs: {}
换成能造成异常的参数:
In : r = div.delay(2, 0)
可以发现每5秒就会重试一次,一共重试3次(默认重复3次),然后抛出异常。
再来一张很给力的图 
celery rabbit mq 详解的更多相关文章
- celery+Rabbit MQ实战记录
基于以前的一篇文章,celery+Rabbit MQ的安装和使用, 本文更加详细的介绍如何安装和使用celey, Rabbit MQ. 并记录在使用celery时遇到的一些问题. 1.安装 Rabbi ...
- JMS与MQ详解(有项目)
<一>m2mGW项目 1.ActiveMQ概述 企业消息软件从80年代起就存在,它不只是一种应用间消息传递风格,也是一种集成风格.因此,消息传递可以满足应用间的通知和互相操作.但是 ...
- 消息中间件MQ详解及四大MQ比较
一.消息中间件相关知识 1.概述 消息队列已经逐渐成为企业IT系统内部通信的核心手段.它具有低耦合.可靠投递.广播.流量控制.最终一致性等一系列功能,成为异步RPC的主要手段之一.当今市面上有很多主流 ...
- 消息中间件(一)MQ详解及四大MQ比较
一.消息中间件相关知识 1.概述 消息队列已经逐渐成为企业IT系统内部通信的核心手段.它具有低耦合.可靠投递.广播.流量控制.最终一致性等一系列功能,成为异步RPC的主要手段之一.当今市面上有很多主流 ...
- 消息中间件之MQ详解及四大MQ比较
一.消息中间件相关知识 1.概述 消息队列已经逐渐成为企业IT系统内部通信的核心手段.它具有低耦合.可靠投递.广播.流量控制.最终一致性等一系列功能,成为异步RPC的主要手段之一.当今市面上有很多主流 ...
- 四大MQ比较及MQ详解
消息队列已经逐渐成为企业IT系统内部通信的核心手段.它具有低耦合.可靠投递.广播.流量控制.最终一致性等一系列功能,成为异步RPC的主要手段之 一.当今市面上有很多主流的消息中间件,如老牌的Activ ...
- 详解RPC远程调用和消息队列MQ的区别
PC(Remote Procedure Call)远程过程调用,主要解决远程通信间的问题,不需要了解底层网络的通信机制. RPC框架 知名度较高的有Thrift(FB的).dubbo(阿里的). RP ...
- celery详解
目录 Celery详解 1.背景 2.形象比喻 3.celery具体介绍 3.1 Broker 3.2 Backend 4.使用 4.1 celery架构 4.2 安装redis+celery 4.3 ...
- RabbitMQ安装使用详解
1.下载相应的版本安装:http://www.rabbitmq.com/download.htmleg:http://www.rabbitmq.com/releases/rabbitmq-server ...
随机推荐
- Spring - Spring容器概念及其初始化过程
引言 工作4年多,做了3年的java,每个项目都用Spring,但对Spring一直都是知其然而不知其所以然.鄙人深知Spring是一个高深的框架,正好近期脱离加班的苦逼状态,遂决定从Spring的官 ...
- vue2.0动态绑定图片src属性值初始化时报错
在vue2.0中,经常会使用类似这样的语法 v-bind:src = " imgUrl "(缩写 :src = " imgUrl "),看一个案例 <te ...
- php多态
多态性是指相同的操作或函数.过程可作用于多种类型的对象上并获得不同的结果.不同的对象,收到同一消息将可以产生不同的结果,这种现象称为多态性. 多态性允许每个对象以适合自身的方式去响应共同的消息.多态性 ...
- Piggy Back_KEY
Piggy Back (piggyback.pas/c/cpp) [问题描述] Bessie 和她的姐姐 Elsie 在不同的田块吃草,晚上她们都返回牛棚休息.作为聪明的奶牛,她们想设计一个方案使得步 ...
- Java虚拟中内存分块
Java虚拟机JVM(Java Virtual Machine)中内存分块 JAVA中通常分为5个区域虚拟机栈.堆.方法区.程序计数器.本地方法区.我们一般讲的是Java虚拟机管理的四个区域虚拟机栈. ...
- Select()使用否?
David Treadwell ,Windows Socket 的一位开发者,曾经在他的一篇名为"Developing Transport-Independent Applications ...
- cannot be cast to javax.servlet.Servlet
在第一次开发Maven项目时,maven环境和仓库以及eclipse都和讲师讲解的一样,可是却遇到下面这个问题: java.lang.ClassCastException: servlet.UserS ...
- C-一行或多行文章垂直居中
1 样式效果 2 table布局 li span
- 第八章 关于SQL查询出错的一些问题
问题一:在使用MySQL使用传参查询并返回结果集时,没错,小伙伴们都知道少不了Statement接口和PreparedStatement对象.问题来了,有时竟然查询不了,Debug进去,发现执行的SQ ...
- 【转载】CSS font关键字属性值的简单研究
文章转载自 张鑫旭-鑫空间-鑫生活 http://www.zhangxinxu.com/wordpress/ 原文链接:http://www.zhangxinxu.com/wordpress/?p=5 ...