Part1.2 、RabbitMQ -- Publish/Subscribe 【发布和订阅】
python 目录
(一)、交换 (Exchanges)
-- 1.1 武sir 经典 Exchanges 案例展示。
(二)、临时队列( Temporary queues )
(三)、绑定(Bindings)
(四)、汇总(Putting it all together)
python系列之 RabbitMQ -- Publish/Subscribe 【发布和订阅】
>>前面的部分我们创建了一个工作队列(work queue). 设想是每个任务都能分发到一个 worker【queue】,这一部分我们将会做一些完全不同的事情
-- 我们将会分发一个消息到多个消费方(consumer),这种模式被誉为 发布/订阅(publish/subscribe)模式
>>为了阐明这种模式,我们将要创建一个简单的日志系统。
由两部分程序组成 --
第一部分将要发布日志消息,第二部分接收并打印
在我们的日志系统中每个接收程序(receiver)将接收消息并复制消息内容,这样我们将会运行一个receiver 记录日志到磁盘;与此同时我们运行另一个receiver输入日志到屏幕查看。
本质上,发布日志消息将会广播到所有的 receivers。
前奏:交换 (Exchanges) 【武SIR前-序曲】
exchange类型可用: direct , topic , headers 和 fanout 。
我们将要对最后一种进行讲解 --- fanout
发布订阅和简单的消息队列区别在于,发布订阅会将消息发送给所有的订阅者,而消息队列中的数据被消费一次便消失。所以,RabbitMQ实现发布和订阅时,会为每一个订阅者创建一个队列,而发布者发布消息时,会将消息放置在所有相关队列中。
exchange type = fanout
1、发布者\生产者
import pika
import sys
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='logs',
type='fanout')
message = ' '.join(sys.argv[1:]) or "info: Hello World!"
channel.basic_publish(exchange='logs',
routing_key='',
body=message)
print(" [x] Sent %r" % message)
connection.close()
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='logs',
type='fanout')
result = channel.queue_declare(exclusive=True)
queue_name = result.method.queue
channel.queue_bind(exchange='logs',
queue=queue_name)
print(' [*] Waiting for logs. To exit press CTRL+C')
def callback(ch, method, properties, body):
print(" [x] %r" % body)
channel.basic_consume(callback,
queue=queue_name,
no_ack=True)
channel.start_consuming()
(一)、交换 (Exchanges)
生产者(Producer) 从不将消息直接发送到一个队列(queue)中,实际上,很多时候生产者甚至不知道一个消息是否要分发到所有队列.换言之,生产者(producer)只能够发送消息到一个交换区 Exchange.. 对exchange发送消息是 -->分发到所有队列照中.从生产者producer方接收消息,从另一边将消息push到队列中。exchange必须清楚知道接收到的消息要如何处理. 是要将消息发送到一个指定queue? 是要将消息发送到多个queue? 还是丢弃?这个规则需要通过 exchange type 来定义。

channel.exchange_declare(exchange='logs',type='fanout')
fanout exchange非常简单,你从这个名字中就能猜出来,它将从Producer方收到的消息广播给所有他知道的receiver方。而这正是我们的logger记录所需要的消息。
$ sudo rabbitmqctl list_exchanges
Listing exchanges ...
logs fanout
amq.direct direct
amq.topic topic
amq.fanout fanout
amq.headers headers
...done.
匿名的exchange
channel.basic_publish(exchange='',routing_key='hello', #指定哪个队列。
body=message)
channel.basic_publish(exchange='logs',
routing_key='',
body=message)
(二)、临时队列( Temporary queues )
你应该记得我们之前使用有一个特定名字的队列( hello、task_queue). 设置队列名对我们来说是至关重要的 --- 我们需要给消费方指定同样的队列名字。 要在生产者和消费者之间共享队列,给队列设置一个名字是非常重要的。
result = channel.queue_declare()
- 这样, result.method.queue 包含一个随机的队列名, 比如:看起来像 amq.gen-JzTY20BRgKO-HjmUJj0wLg.
- 其次,一旦我们断开consumer连接,这个队列名将自动删除。这里有一个标识设置:
result = channel.queue_declare(exclusive=True)
(三)、绑定(Bindings)

channel.queue_bind(exchange='logs',
queue=result.method.queue) #固定的写法
现在logs exchange 将要发送消息到我们的队列
你可以在Server端通过rabbitmqctl list_bindings命令查看绑定信息
(四)、汇总(Putting it all together)

- 我们之前使用匿名exchange发送消息时Producer需要提供一个 routing_key,这样就直接绑定到__队列上,, 跳过了中间件的 exchange。
- 但当我们指定exchange为fanout exchange时,这个值(routing_key)将忽略。
import pika
import sys
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='logs',
type='fanout')
message = ' '.join(sys.argv[1:]) or "info: Hello World!"
channel.basic_publish(exchange='logs',
routing_key='',
body=message)
print(" [x] Sent %r" % message)
connection.close()
如你所见, 当建立连接之后我们定义了一个exchange名logs, 由于发布一个消息到一个不存在的exchange是禁止的,所以这一步是必须有的。
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='logs',
type='fanout')
result = channel.queue_declare(exclusive=True) # 队列断开后自动删除临时队列
queue_name = result.method.queue # 队列名采用服务端分配的临时队列
channel.queue_bind(exchange='logs',
queue=queue_name)
print(' [*] Waiting for logs. To exit press CTRL+C')
def callback(ch, method, properties, body):
print(" [x] %r" % body)
channel.basic_consume(callback,
queue=queue_name,
no_ack=True)
channel.start_consuming()
$ python receive_logs.py > logs_from_rabbit.log
$ python receive_logs.py
$ python emit_log.py
$ sudo rabbitmqctl list_bindings
Listing bindings ...
logs exchange amq.gen-JzTY20BRgKO-HjmUJj0wLg queue []
logs exchange amq.gen-vso0PVvyiRIL2WoV3i48Yg queue []
...done.
这个结果的解释非常直白: 从 logs exchange 出来的数据发送服务端自动分配的到两个队列名中,这也是我们预期的。
Part1.2 、RabbitMQ -- Publish/Subscribe 【发布和订阅】的更多相关文章
- 译: 3. RabbitMQ Spring AMQP 之 Publish/Subscribe 发布和订阅
在第一篇教程中,我们展示了如何使用start.spring.io来利用Spring Initializr创建一个具有RabbitMQ starter dependency的项目来创建spring-am ...
- 【python】-- RabbitMQ Publish\Subscribe(消息发布\订阅)
RabbitMQ RabbitMQ Publish\Subscribe(消息发布\订阅) 1对1的消息发送和接收,即消息只能发送到指定的queue里,但这样使用有些局限性,有些时候你想让你的消息被所有 ...
- php redis pub/sub(Publish/Subscribe,发布/订阅的信息系统)之基本使用
一.场景介绍 最近的一个项目需要用到发布/订阅的信息系统,以做到最新实时消息的通知.经查找后发现了redis pub/sub(发布/订阅的信息系统)可以满足我的开发需求,而且学习成本和使用成本也比较低 ...
- RabbitMQ --- Publish/Subscribe(发布/订阅)
目录 RabbitMQ --- Hello Mr.Tua RabbitMQ --- Work Queues(工作队列) 前言 在第二篇文章中介绍了 Work Queues(工作队列),它适用于把一个消 ...
- RabbitMQ学习总结 第四篇:发布/订阅 Publish/Subscribe
目录 RabbitMQ学习总结 第一篇:理论篇 RabbitMQ学习总结 第二篇:快速入门HelloWorld RabbitMQ学习总结 第三篇:工作队列Work Queue RabbitMQ学习总结 ...
- RabbitMQ系列教程之三:发布/订阅(Publish/Subscribe)(转载)
RabbitMQ系列教程之三:发布/订阅(Publish/Subscribe) (本教程是使用Net客户端,也就是针对微软技术平台的) 在前一个教程中,我们创建了一个工作队列.工作队列背后的假设是每个 ...
- RabbitMQ入门:发布/订阅(Publish/Subscribe)
在前面的两篇博客中 RabbitMQ入门:Hello RabbitMQ 代码实例 RabbitMQ入门:工作队列(Work Queue) 遇到的实例都是一个消息只发送给一个消费者(工作者),他们的消息 ...
- RabbitMQ入门(3)——发布/订阅(Publish/Subscribe)
在上一篇RabbitMQ入门(2)--工作队列中,有一个默认的前提:每个任务都只发送到一个工作人员.这一篇将介绍发送一个消息到多个消费者.这种模式称为发布/订阅(Publish/Subscribe). ...
- RabbitMQ入门教程(五):扇形交换机发布/订阅(Publish/Subscribe)
原文:RabbitMQ入门教程(五):扇形交换机发布/订阅(Publish/Subscribe) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. ...
随机推荐
- 在Linux下搭建git服务器
http://www.cnblogs.com/dee0912/p/5815267.html 步骤很详细,很受用
- 错误 1 error C4996: 'scanf': This function or variable may be unsafe. Consider using scanf_s instead
错误简介 在VS 2012 中编译 C 语言项目,如果使用了 scanf 函数,编译时便会提示如下错误: 原因是Visual C++ 2012 使用了更加安全的 run-time library ro ...
- pipe_wait问题_转
转自:调用Process.waitfor导致的进程挂起 最近遇到pipe_wait问题,父进程调用子进程时,子进程阻塞,cat /proc/$child/wchan输出pipe_wait,进程阻塞在p ...
- hdu5745 La Vie en rose 巧妙地dp+bitset优化+滚动数组减少内存
/** 题目:hdu5745 La Vie en rose 链接:http://acm.hdu.edu.cn/showproblem.php?pid=5745 题意:题目给出的变换规则其实就是交换相邻 ...
- 基于nc实现聊天
需要 Netcat(在网络上通过 TCP 或 UDP 读写数据),CentOS 6.x 系统中默认没有安装,经过测试,如果通过 yum 直接安装,运行时会有 “nc: Protocol not ava ...
- 档案 & 权限管理
1. owner, group, others root 是万能的天神 权限 连结档 owner group 容量 修改日期 档名 2. chown, chgrp, chmod chgrp –R ro ...
- J2EE是什么?
解答:从整体上讲,J2EE是使用Java技术开发企业级应用的工业标准,它是Java技术不断适应和促进企业级应用过程中的产物.适用于企业级应用的J2EE,提供一个平台独立的.可移植的.多用户的.安全的和 ...
- oracledbconsole db启动问题
oracledbconsole db启动问题 被这个OracleDBconsole服务无法启动的问题折磨了两个星期了,今天很幸运,在网上无意间看到了一位大侠的思路,虽然错误的情况并不完全相同,但他的思 ...
- PHP 清除HTML代码、空格、回车换行符的函数
function DeleteHtml($str) { $str = trim($str); $str = strip_tags($str,""); $str = ereg_rep ...
- Spark源码分析(四)-Job提交过程
原创文章,转载请注明: 转载自http://www.cnblogs.com/tovin/p/3903478.html 本文将以一个简单的WordCount为例来看看Job的提交过程