前面的部分我们创建了一个工作队列(work queue). 设想是每个任务都能分发到一个worker,这一部分我们将会做一些完全不同的事情 -- 我们将会分发一个消息到多个消费方(consumer),这种模式被誉为发布/订阅(publish/subscribe)模式
为了阐明这种模式,我们将要创建一个简单的日志系统,由两部分程序组成 -- 第一部分将要发布日志消息,第二部分接收并打印
在我们的日志系统中每个接收程序(receiver)将接收消息并复制消息内容,这样我们将会运行一个receiver 记录日志到磁盘;与此同时我们运行另一个receiver输入日志到屏幕查看。
本质上,发布日志消息将会广播到所有的receivers
channel.exchange_declare(exchange='logs',
type='fanout')
$ sudo rabbitmqctl list_exchanges
Listing exchanges ...
logs fanout
amq.direct direct
amq.topic topic
amq.fanout fanout
amq.headers headers
...done.
channel.basic_publish(exchange='',
routing_key='hello',
body=message)
这个exchange参数就是这个exchange的名字. 空字符串标识默认的或者匿名的exchange:如果存在routing_key, 消息路由到routing_key指定的队列中。
channel.basic_publish(exchange='logs',
routing_key='',
body=message)
result = channel.queue_declare()
result = channel.queue_declare(exclusive=True)
channel.queue_bind(exchange='logs',
queue=result.method.queue)
现在logs exchange 将要发送消息到我们的队列
你可以在Server端通过rabbitmqctl list_bindings命令查看绑定信息
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()
$ 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 出来的数据发送服务端自动分配的到两个队列名中,这也是我们预期的。