RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)
来源:互联网 发布:四川房卡麻将源码 编辑:程序博客网 时间:2024/05/01 10:07
这篇文章中,我们将创建一个日志系统,它包含两个部分:第一个部分是发出log(Producer),第二个部分接收到并打印(Consumer)。 我们将构建两个Consumer,第一个将log写到物理磁盘上;第二个将log输出的屏幕。
1. Exchanges
关于exchange的概念在《RabbitMQ消息队列(一): Detailed Introduction 详细介绍》中有详细介绍。现在做一下简单的回顾。
RabbitMQ 的Messaging Model就是Producer并不会直接发送Message到queue。实际上,Producer并不知道它发送的Message是否已经到达queue。
Producer发送的Message实际上是发到了Exchange中。它的功能也很简单:从Producer接收Message,然后投递到queue中。Exchange需要知道如何处理Message,是把它放到那个queue中,还是放到多个queue中?这个rule是通过Exchange 的类型定义的。
我们知道有三种类型的Exchange:direct, topic 和fanout。fanout就是广播模式,会将所有的Message都放到它所知道的queue中。创建一个名字为logs,类型为fanout的Exchange:
- channel.exchange_declare(exchange='logs',
- type='fanout')
Listing exchanges
通过rabbitmqctl可以列出当前所有的Exchange:
- $ sudo rabbitmqctl list_exchanges
- Listing exchanges ...
- logs fanout
- amq.direct direct
- amq.topic topic
- amq.fanout fanout
- amq.headers headers
- ...done.
注意 amq.* exchanges 和the default (unnamed)exchange是RabbitMQ默认创建的。
现在我们可以通过exchange,而不是routing_key来publish Message了:
- channel.basic_publish(exchange='logs',
- routing_key='',
- body=message)
2. Temporary queues
截至现在,我们用的queue都是有名字的:第一个是hello,第二个是task_queue。使用有名字的queue,使得在Producer和Consumer之前共享queue成为可能。
但是对于我们将要构建的日志系统,并不需要有名字的queue。我们希望得到所有的log,而不是它们中间的一部分。而且我们只对当前的log感兴趣。为了实现这个目标,我们需要两件事情:1) 每当Consumer连接时,我们需要一个新的,空的queue。因为我们不对老的log感兴趣。幸运的是,如果在声明queue时不指定名字,那么RabbitMQ会随机为我们选择这个名字。方法:
- result = channel.queue_declare()
2)当Consumer关闭连接时,这个queue要被deleted。可以加个exclusive的参数。方法:
- result = channel.queue_declare(exclusive=True)
3. Bindings绑定
方法:
- channel.queue_bind(exchange='logs',
- queue=result.method.queue)
使用命令rabbitmqctl list_bindings。
4. 最终版本
我们最终实现的数据流图如下:
Producer,在这里就是产生log的program,基本上和前几个都差不多。最主要的区别就是publish通过了exchange而不是routing_key。
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()
Consumer: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()
其实用重定向就可以了,当然你想修改callback自己写文件也行。我们使用重定向的方法:
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
- $ python receive_logs.py
- $ python emit_log.py
一个output:
- $ sudo rabbitmqctl list_bindings
- Listing bindings ...
- logs exchange amq.gen-JzTY20BRgKO-HjmUJj0wLg queue []
- logs exchange amq.gen-vso0PVvyiRIL2WoV3i48Yg queue []
- ...done.
参考资料:
1. http://www.rabbitmq.com/tutorials/tutorial-three-Python.html
- RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)(转)
- RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)
- RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)
- RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)
- RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)
- RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)
- RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)
- RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)
- RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)
- RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)[转]
- RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)[转]
- RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)
- RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)
- RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)
- (四) RabbitMQ消息分发模式----"Publish/Subscribe"发布/订阅模式
- SpringBoot的RabbitMQ消息队列: 四、第三模式"Publish/Subscribe"
- SpringBoot的RabbitMQ消息队列: 四、第三模式"Publish/Subscribe"
- RabbitMQ (消息队列)专题学习04 Publish/Subscribe(发布者/订阅者)
- 开发中项目的版本管理和svn使用(下)
- 【重点】初窥Linux 之 我最常用的20多条命令
- Unity&Shader案例篇—膨胀效果
- 如何实现数据库批量插入oracle11g
- jQuery学习笔记:DOM操作(一)——文档
- RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)
- 每天一个 Linux 命令(19):find 命令概览
- vue填坑之回到顶部:
- STM32存储器地址映射
- android 如何创建配置文件和读配置文件
- Struts2获取action
- RepositoryItemComboBox获得焦点弹出下拉框
- JAVA程序员必看的15本书-JAVA自学书籍推荐
- RabbitMQ (三) 发布/订阅