celery+Rabbit MQ实战记录
基于以前的一篇文章,celery+Rabbit MQ的安装和使用,
本文更加详细的介绍如何安装和使用celey, Rabbit MQ。
并记录在使用celery时遇到的一些问题。
1.安装 Rabbit MQ
在 OS X上,直接执行如下命令:
$ brew install rabbitmq
其他操作系统下的安装可以参考安装 RabbitMQ
启动RabbitMQ
$ sudo rabbitmq-server
你也可以添加 -detached 属性来让它在后台运行(注意:只有一个破折号):
$ sudo rabbitmq-server -detached
查看RabbitMQ状态
$ sudo rabbitmqctl status
停止RabbitMQ
永远不要用 kill 停止 RabbitMQ 服务器,而是应该用 rabbitmqctl 命令:
$ sudo rabbitmqctl stop
添加用户
默认用户guest,密码guest,只允许本地访问,如需远程访问,需要设置.
$ sudo rabbitmqctl add_user test 123456
Adding user "test" ...
添加虚拟主机,并赋予用户test权限
$ sudo rabbitmqctl add_vhost myvhost
Adding vhost "myvhost" ...
$ sudo rabbitmqctl set_permissions -p myvhost test ".*" ".*" ".*"
Setting permissions for user "test" in vhost "myvhost" ...
2.安装celery
2.1 创建虚拟环境,并安装celery
$ mkdir celery_demo
$ cd celery_demo
$ virtualenv -p python3 venv3
$ ./venv3/bin/pip install celery
2.2 配置celery
创建配置文件 celeryconfig.py,里面包含BROKER_URL、CELERYD_LOG_FORMAT、CELERY_ROUTES.
# celeryconfig.py
RABBIT_MQ = {
'HOST': '127.0.0.1',
'PORT': 5672,
'USER': 'test',
'PASSWORD': '123456'
}
# broker
BROKER_URL = 'amqp://%s:%s@%s:%s/myvhost' % (RABBIT_MQ['USER'], RABBIT_MQ['PASSWORD'], RABBIT_MQ['HOST'], RABBIT_MQ['PORT'])
# celery日志格式
CELERYD_LOG_FORMAT = '[%(asctime)s] [%(levelname)s] %(message)s'
CELERY_ROUTES = {
'demo_task.add': {'queue': 'sunday'},
}
其中,参数定义如下:
BROKER_URL指定了broker信息,即消息队列的地址。CELERYD_LOG_FORMAT指定了日志格式。CELERY_ROUTES指定了路由信息,即调用demo_task.add后,消息具体放入哪个队列,这里是队列名称为sunday。
2.3 启动消费者
消费者
消费者代码如下:
# demo_task.py
from celery import Celery
app = Celery("orange", backend='amqp')
app.config_from_object("celeryconfig")
@app.task
def add(x, y):
return x + y
首先,创建Celery实例,从文件中读取配置。
接着,定义task。
其中,在创建Celery实例时,参数backend指定了结果存储后端,用于追踪task执行状态和结果。这里使用amqp,即使用RabbitMQ保存结果。默认情况下,backend参数是关闭的。
使用celery worker启动消费者
./venv3/bin/celery worker -A demo_task -Q sunday --loglevel=info -f app.log
celery@admindeMacBook-Pro-2.local v4.3.0 (rhubarb)
Darwin-18.2.0-x86_64-i386-64bit 2019-04-20 17:49:40
[config]
.> app: orange:0x109ca0400
.> transport: amqp://test:**@127.0.0.1:5672/myvhost
.> results: disabled://
.> concurrency: 8 (prefork)
.> task events: OFF (enable -E to monitor tasks in this worker)
[queues]
.> sunday exchange=sunday(direct) key=sunday
[tasks]
. demo_task.add
其中,参数定义如下:
参数
-A是app name,即定义celery的文件。参数
-Q指定了队列的名称,如果不指定,默认为celery。参数
-f指定了日志打印文件。
可以通过以下命令查看更多帮助信息:
celery help查看celery的选项celery worker --help查看worker的选项
2.4 启动生产者
生产者
代码如下api.py所示:
# api.py
from demo_task import add
print("start...")
result = add.apply_async((1, 2))
print("result:", result)
print(result.ready())
print("end...")
代码中,将1、2参数放入消息队列。
celery配置backend参数后, 调用任务时,会返回 AsyncResult 实例。
AsyncResult 的ready() 方法可以查看任务是否完成处理。
执行api.py
执行结果分两种情况:worker启动和没有启动。
当celery worker启动的时候,结果如下:
./venv3/bin/python api.py
start...
result: 60dd0ab6-5fa2-4190-954e-584eb519384f
True
end...
可以看到,task很快得到执行,结果状态为True。
当celery worker没有启动的时候,结果如下:
./venv3/bin/python api.py
start...
result: 7280466f-73cd-44ec-85e7-5ad4f079a797
False
end...
可以看到,结果状态为False。
直接获取结果
可以使用get()函数等待任务完成,但这很少使用,因为它把异步调用变成了同步调用。
对于get()的使用,按照是否设置超时参数,分为两种:不使用超时参数timeout和使用超时参数timeout。
(1)不使用超时参数timeout
默认timeout为None,不会超时,而是阻塞住。
通过tcpdump抓包,可以发现,get调用后,每隔30s,RabbitMQ(server端)向生产者API(client端)发送心跳包,共发了5次。
最后,过了3分钟,RabbitMQ(server端)关闭连接,生产者API(client端)也关闭连接,报错:
start...
result: aae4fb20-823c-4674-8bff-28429f14d5d7
False
Traceback (most recent call last):
File "api.py", line 13, in <module>
result.get()
File "/workspace/celery_demo/venv3/lib/python3.6/site-packages/celery/result.py", line 226, in get
on_message=on_message,
File "/workspace/celery_demo/venv3/lib/python3.6/site-packages/celery/backends/base.py", line 496, in wait_for_pending
no_ack=no_ack,
File "/workspace/celery_demo/venv3/lib/python3.6/site-packages/celery/backends/amqp.py", line 146, in wait_for
on_interval=on_interval)
File "/workspace/celery_demo/venv3/lib/python3.6/site-packages/celery/backends/amqp.py", line 223, in consume
conn, consumer, timeout, on_interval)[task_id]
File "/workspace/celery_demo/venv3/lib/python3.6/site-packages/celery/backends/amqp.py", line 204, in drain_events
wait(timeout=1)
File "/workspace/celery_demo/venv3/lib/python3.6/site-packages/kombu/connection.py", line 315, in drain_events
return self.transport.drain_events(self.connection, **kwargs)
File "/workspace/celery_demo/venv3/lib/python3.6/site-packages/kombu/transport/pyamqp.py", line 103, in drain_events
return connection.drain_events(**kwargs)
File "/workspace/celery_demo/venv3/lib/python3.6/site-packages/amqp/connection.py", line 500, in drain_events
while not self.blocking_read(timeout):
File "/workspace/celery_demo/venv3/lib/python3.6/site-packages/amqp/connection.py", line 505, in blocking_read
frame = self.transport.read_frame()
File "/workspace/celery_demo/venv3/lib/python3.6/site-packages/amqp/transport.py", line 256, in read_frame
frame_header = read(7, True)
File "/workspace/celery_demo/venv3/lib/python3.6/site-packages/amqp/transport.py", line 448, in _read
raise IOError('Server unexpectedly closed connection')
OSError: Server unexpectedly closed connection
(2)使用超时参数timeout
如果使用timeout参数,get(timeout)调用发起后, 当超过timeout指定的时间仍然没有获得结果,会超时报错。
例如,调用get(timeout=1):
... ...
# sync
print(result.get(timeout=1))
print("end...")
如果worker没有启动或者worker处理超时,get会报超时错误:
start...
result: 190ad871-aae2-48ac-a18e-962cd2d537b7
False
Traceback (most recent call last):
File "/workspace/celery_demo/venv3/lib/python3.6/site-packages/celery/backends/amqp.py", line 146, in wait_for
on_interval=on_interval)
File "/workspace/celery_demo/venv3/lib/python3.6/site-packages/celery/backends/amqp.py", line 223, in consume
conn, consumer, timeout, on_interval)[task_id]
File "/workspace/celery_demo/venv3/lib/python3.6/site-packages/celery/backends/amqp.py", line 202, in drain_events
raise socket.timeout()
socket.timeout
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "api.py", line 14, in <module>
print(result.get(timeout=1))
File "/workspace//celery_demo/venv3/lib/python3.6/site-packages/celery/result.py", line 226, in get
on_message=on_message,
File "/workspace/celery_demo/venv3/lib/python3.6/site-packages/celery/backends/base.py", line 496, in wait_for_pending
no_ack=no_ack,
File "/workspace/celery_demo/venv3/lib/python3.6/site-packages/celery/backends/amqp.py", line 148, in wait_for
raise TimeoutError('The operation timed out.')
celery.exceptions.TimeoutError: The operation timed out.
2.5 查看结果
查看app.log中的日志
[2019-04-20 20:53:59,327] [INFO] Connected to amqp://test:**@127.0.0.1:5672/myvhost
[2019-04-20 20:53:59,345] [INFO] mingle: searching for neighbors
[2019-04-20 20:54:00,379] [INFO] mingle: all alone
[2019-04-20 20:54:00,441] [INFO] celery@admindeMacBook-Pro-2.local ready.
[2019-04-20 20:55:46,498] [INFO] Received task: demo_task.add[1c8d47bd-449d-4bd9-b4db-819777081d23]
[2019-04-20 20:55:46,561] [INFO] Task demo_task.add[1c8d47bd-449d-4bd9-b4db-819777081d23] succeeded in 0.060540573904290795s: 3
3.任务过期
调用apply_async时使用参数expires,则表示任务有超时时间,超过这个时间后,task不会得到执行。
result = add.apply_async((1, 2), expires=10)
当worker没有启动或者其他异常情况下,会出现任务超时,不被执行。
查看日志,可以看到task过期,不会被执行。
[2019-04-20 21:32:45,828] [INFO] Received task: demo_task.add[12691c27-3f2f-4c96-9b4e-54636e20d0eb] expires:[2019-04-20 13:31:51.030013+00:00]
[2019-04-20 21:32:45,829] [INFO] Discarding revoked task: demo_task.add[12691c27-3f2f-4c96-9b4e-54636e20d0eb]
3.参考
celery+Rabbit MQ实战记录的更多相关文章
- celery rabbit mq 详解
Celery介绍和基本使用 Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery, ...
- celery+RabbitMQ 实战记录2—工程化使用
上篇文章中,已经介绍了celery和RabbitMQ的安装以及基本用法. 本文将从工程的角度介绍如何使用celery. 1.配置和启动RabbitMQ 请参考celery+RabbitMQ实战记录. ...
- Rabbit MQ config文件解析
Rabbit MQ config文件解析 tcp_listeners:用于监听AMQP连接的端口或主机名/对(不带TLS),默认端口:5672 2.numtcpacceptors :将接受TCP侦听器 ...
- Spring Boot:使用Rabbit MQ消息队列
综合概述 消息队列 消息队列就是一个消息的链表,可以把消息看作一个记录,具有特定的格式以及特定的优先级.对消息队列有写权限的进程可以向消息队列中按照一定的规则添加新消息,对消息队列有读权限的进程则可以 ...
- 使用Rabbit MQ消息队列
使用Rabbit MQ消息队列 综合概述 消息队列 消息队列就是一个消息的链表,可以把消息看作一个记录,具有特定的格式以及特定的优先级.对消息队列有写权限的进程可以向消息队列中按照一定的规则添加新消息 ...
- redis反向代理docker容器中的rabbit mq服务
最近做的项目中用到了docker,发现docker容器还真挺好用的,可以统一来管理各种资源,项目. 但是在实际使用中就碰到下面这个问题(下面所有的应用都是在docker中启动的): 通过nginx来反 ...
- 在 Windows 上安装Rabbit MQ 指南
rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.他遵循Mozilla Public License开源协议.采用 Erlang 实现的工业级的消息队列(MQ)服务器. Ra ...
- windows下的php rabbit mq安装、配置
http://www.cnblogs.com/shanyou/p/4067250.html 这篇博文写的rabbit mq和erlang的安装以及rabbitmq可视化插件的一些操作 接下去开始安装P ...
- (转)在 Windows 上安装Rabbit MQ 指南
rabbitMQ是一个在AMQP协议标准基础上完整的,可服用的企业消息系统.他遵循Mozilla Public License开源协议.采用 Erlang 实现的工业级的消息队列(MQ)服务器. Ra ...
随机推荐
- springboot整合ueditor 前后端分离
1.下载ueditor,百度搜索ueditor,下载 前端用的是Jsp版,导入文件如下 由于要修改部分源码,所以后端用的源码版,导入文件如下 2.配置路径,用来找到json文件 配置前端ueditor ...
- 2018-2019-2 20175224 实验一《Java开发环境的熟悉》实验报告
实验报告封面 实验内容与步骤 Java开发环境的熟悉-1 1.建立“自己学号exp1”的目录 2.在“自己学号exp1”目录下建立src,bin等目录 3.javac.java的执行在“自己学号exp ...
- 关于redis实现分布式锁
前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...
- Maven中添加镜像
Maven库在天朝的下载速度实在是感人,所以添加镜像之后速度会提升很多. 在maven的settings.xml 文件里配置mirrors的子节点,添加如下mirror <mirror> ...
- Python第五章(北理国家精品课 嵩天等)
函数和代码复用 函数的定义和使用 def <函数名>(<参数(0个或多个)>): <函数体> return <返回值>可选参数放在不可选参数之后*b不定 ...
- python 语法的一些特性记录
装饰器@符号 装饰器本质上是一个 Python 函数或类,它可以让其他函数或类在不需要做任何代码修改的前提下增加额外功能,装饰器的返回值也是一个函数/类对象.它经常用于有切面需求的场景,比如:插入日志 ...
- Java Web安全之程序逻辑缺陷
Java Web程序逻辑缺陷本质是由于程序设计和开发者设计的程序执行逻辑存在某种缺陷而导致的安全隐患.企业的代码审查和渗透测试通常主要针对的大多是诸如xss攻击和sql注入和跨站点脚本这些头条式漏洞, ...
- Breadth-first search
given a graph G and a distinguished source vertex s, breadth-firstsearch systematically explores th ...
- @RequestMapping、@ResponseBody和@RequestBody的使用
使用SSM框架进行Web开发时,经常在Controller中遇到@RequestMapping.@ResponseBody和@RequestMapping注解. 1.@RequsetMapping注解 ...
- 《Pro SQL Server Internals, 2nd edition》15w
第三章 统计 SQL Server查询优化器在为查询选择执行计划时使用基于成本的模型.它估计不同执行计划的成本,并选择成本最低的一个.但是,请记住,SQL Server并不搜索可用于查询的最佳执行计划 ...