rabbitmq使用(三)
Publish/Subscribe
In the previous tutorial we created a work queue. The assumption behind a work queue is that each task is delivered to exactly one worker. In this part we'll do something completely different -- we'll deliver a message to multiple consumers. This pattern is known as "publish/subscribe".
To illustrate the pattern, we're going to build a simple logging system. It will consist of two programs -- the first will emit log messages and the second will receive and print them.
In our logging system every running copy of the receiver program will get the messages. That way we'll be able to run one receiver and direct the logs to disk; and at the same time we'll be able to run another receiver and see the logs on the screen.
Essentially, published log messages are going to be broadcast to all the receivers.
Exchanges
In previous parts of the tutorial we sent and received messages to and from a queue. Now it's time to introduce the full messaging model in Rabbit.
Let's quickly go over what we covered in the previous tutorials:
- A producer is a user application that sends messages.
- A queue is a buffer that stores messages.
- A consumer is a user application that receives messages.
The core idea in the messaging model in RabbitMQ is that the producer never sends any messages directly to a queue. Actually, quite often the producer doesn't even know if a message will be delivered to any queue at all.
Instead, the producer can only send messages to an exchange. An exchange is a very simple thing. On one side it receives messages from producers and the other side it pushes them to queues. The exchange must know exactly what to do with a message it receives. Should it be appended to a particular queue? Should it be appended to many queues? Or should it get discarded. The rules for that are defined by the exchange type.

There are a few exchange types available: direct, topic, headers and fanout. We'll focus on the last one -- the fanout. Let's create an exchange of that type, and call it logs:
channel.exchange_declare(exchange='logs',
type='fanout')
The fanout exchange is very simple. As you can probably guess from the name, it just broadcasts all the messages it receives to all the queues it knows. And that's exactly what we need for our logger.
Now, we can publish to our named exchange instead:
channel.basic_publish(exchange='logs',
routing_key='',
body=message)
Temporary queues
As you may remember previously we were using queues which had a specified name (remember hello and task_queue?). Being able to name a queue was crucial for us -- we needed to point the workers to the same queue. Giving a queue a name is important when you want to share the queue between producers and consumers.
But that's not the case for our logger. We want to hear about all log messages, not just a subset of them. We're also interested only in currently flowing messages not in the old ones. To solve that we need two things.
Firstly, whenever we connect to Rabbit we need a fresh, empty queue. To do it we could create a queue with a random name, or, even better - let the server choose a random queue name for us. We can do this by not supplying the queue parameter to queue_declare:
result = channel.queue_declare()
At this point result.method.queue contains a random queue name. For example it may look like amq.gen-JzTY20BRgKO-HjmUJj0wLg.
Secondly, once we disconnect the consumer the queue should be deleted. There's an exclusive flag for that:
result = channel.queue_declare(exclusive=True)
Bindings

We've already created a fanout exchange and a queue. Now we need to tell the exchange to send messages to our queue. That relationship between exchange and a queue is called abinding.
channel.queue_bind(exchange='logs',
queue=result.method.queue)
From now on the logs exchange will append messages to our queue.
Putting it all together

The producer program, which emits log messages, doesn't look much different from the previous tutorial. The most important change is that we now want to publish messages to our logs exchange instead of the nameless one. We need to supply a routing_key when sending, but its value is ignored for fanout exchanges. Here goes the code for emit_log.py script:
#!/usr/bin/env python
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()
As you see, after establishing the connection we declared the exchange. This step is neccesary as publishing to a non-existing exchange is forbidden.
The messages will be lost if no queue is bound to the exchange yet, but that's okay for us; if no consumer is listening yet we can safely discard the message.
The code for receive_logs.py:
#!/usr/bin/env python
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()
We're done. If you want to save logs to a file, just open a console and type:
$ python receive_logs.py > logs_from_rabbit.log
If you wish to see the logs on your screen, spawn a new terminal and run:
$ python receive_logs.py
And of course, to emit logs type:
$ python emit_log.py
Using rabbitmqctl list_bindings you can verify that the code actually creates bindings and queues as we want. With two receive_logs.py programs running you should see something like:
$ sudo rabbitmqctl list_bindings
Listing bindings ...
logs exchange amq.gen-JzTY20BRgKO-HjmUJj0wLg queue []
logs exchange amq.gen-vso0PVvyiRIL2WoV3i48Yg queue []
...done.
rabbitmq使用(三)的更多相关文章
- RabbitMQ(三) -- Publish/Subscribe
RabbitMQ(三) -- Publish/Subscribe `rabbitmq`支持一对多的模式,一般称为发布/订阅.也就是说,生产者产生一条消息后,`rabbitmq`会把该消息分发给所有的消 ...
- rabbitMQ第三篇:采用不同的交换机规则
在上一篇我们都是采用发送信息到队列然后队列把信息在发送到消费者,其实实际情况并非如此,rabbitMQ其实真正的思想是生产者不发送任何信息到队列,甚至不知道信息将发送到哪个队列.相反生产者只能发送信息 ...
- python使用rabbitMQ介绍三(发布订阅模式)
一.模式介绍 在前面的例子中,消息直接发送到queue中. 现在介绍的模式,消息发送到exchange中,消费者把队列绑定到exchange上. 发布-订阅模式是把消息广播到每个消费者,每个消费者接收 ...
- 【RabbitMQ】三种类型交换器 Fanout,Direct,Topic(转)
出处:https://blog.csdn.net/fxq8866/article/details/62049393 RabbitMQ服务器会根据路由键将消息从交换器路由到队列中,如何处理投递到多个队列 ...
- rabbitMQ的三种路由模式
rabbitMQ工作流程: 1.声明交换机 2.声明消息队列 3.绑定交换机和队列 4.生产者往交换机里发送新消息 5.交换机根据所选的模式和routingKey决定消息发往哪条消息队列 6.一个消费 ...
- RabbitMQ系列(三)--Java API
基于java使用RabbitMQ 框架:SpringBoot1.5.14.RELEASE maven依赖: <dependency> <groupId>com.rabbitmq ...
- RabbitMQ实战(三)-高级特性
0 相关源码 1 你将学到 如何保证消息百分百投递成功 幂等性 如何避免海量订单生成时消息的重复消费 Confirm确认消息.Return返回消息 自定义消费者 消息的ACK与重回队列 限流 TTL ...
- RabbitMQ(三):RabbitMQ与Spring Boot简单整合
RabbitMQ是目前非常热门的一款消息中间件,不管是互联网大厂还是中小企业都在大量使用.Spring Boot的兴起,极大地简化了Spring的开发,本文将使用Spring Boot与RabbitM ...
- 消息中间件——RabbitMQ(三)理解RabbitMQ核心概念和AMQP协议!
前言 本章学习,我们可以了解到以下知识点: 互联网大厂为什么选择RabbitMQ? RabbiMQ的高性能之道是如何做到的? 什么是AMQP高级协议? AMQP核心概念是什么? RabbitMQ整体架 ...
- Rabbitmq交换机三种模式介绍
1.topic 将路由键和某模式进行匹配.此时队列需要绑定要一个模式上.符号“#”匹配一个或多个词,符号“*”匹配不多不少一个词.因此“abc.#”能够匹配到“abc.def.ghi”,但是“abc. ...
随机推荐
- jQuery 实现添加表格行,删除行,调用日期控件
$(function () { getdatepicker(); getdatetimepicker(); }); $(document).on('click','#addTable',addTr); ...
- ES系列五、ES6.3常用api之搜索类api
1.搜索api 1.1.routing:路由 执行搜索时,它将广播到所有索引/索引分片(副本之间的循环).可以通过提供routing参数来控制将搜索哪些分片.例如,在索引book时,路由值可以是nam ...
- Javascript构造函数的继承
仅供学习参考,原文链接:http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html 今天要介绍 ...
- linux/centos6.5下编译安装python2.7和python3.5.2
centos6.5环境下安装python2.7 解压python源码包 tar -xf Python-2.7.6.tar.xz 进入软件包目录 cd Python-2.7.6 添加配置项 ./conf ...
- GBDT学习
白话GBDT: https://blog.csdn.net/qq_26598445/article/details/80853873 优点: 预测精度高 适合低维数据 能处理非线性数据,该版本GBDT ...
- 测试开发之前端——No6.HTML5中的键盘事件
键盘事件 由键盘触发的事件. 适用于所有 HTML 5 元素: 属性 值 描述 onkeydown script 当按下按键时运行脚本 onkeypress script 当按下并松开按键时运行脚本 ...
- 关于引用外部类要用static 的问题
一.直接用 static 引用 import static net.mindview.util.Print.*; //net...为引用的类,此方法在程序加载时就已实例化 二. 也可以手动在需要时实例 ...
- MySQL 由 5.7 升级为 8.0 之后,Laravel 的配置改动
开发机上升级了 MySQL 8.0, 原有的 Laravel 5.5 项目就启动失败了. 报错信息是: [2018-05-30 11:17:37] local.ERROR: SQLSTATE[4200 ...
- pyinstaller将py文件转成exe格式
首先要注意一下:打包python文件成exe格式这个过程只能在windows环境下运行 1. 直接在命令行用pip安装 pyinstaller pip install pyinstaller 2. 下 ...
- hdu 1372 骑士从起点走到终点的步数 (BFS)
给出起点和终点 求骑士从起点走到终点所需要的步数 Sample Inpute2 e4 //起点 终点a1 b2b2 c3a1 h8a1 h7h8 a1b1 c3f6 f6 Sample OutputT ...