官网就是最好的文档
上一篇文章RabbitMq Publish/Subscribe消息发布订阅模式 消息发布订阅模式中,就是通过广播来实现分发的。所有的customer都能够收到全部的消息。实际业务场景是需要filter的,怎么办?
我们将为其添加一个功能 - 我们将只能订阅一部分消息。例如,我们只能将关键错误消息定向到日志文件(以节省磁盘空间),同时仍然能够在控制台上打印所有日志消息。
在前面的例子中,我们已经创建了绑定。您可能会记得以下代码:
channel.queue_bind(exchange=exchange_name,
queue=queue_name)
绑定是交换和队列之间的关系。这可以简单地理解为:队列对来自此交换的消息感兴趣。
绑定可以采用额外的routing_key参数。为了避免与basic_publish参数混淆,我们将其称为 绑定密钥。这就是我们如何使用键创建绑定
channel.queue_bind(exchange=exchange_name,
queue=queue_name,
routing_key='black')
其实就是加了一个routing_key 参数
绑定密钥的含义取决于交换类型。我们之前使用的 fanout交换只是忽略了它的价值。
我们希望扩展以允许根据消息的严重性过滤消息。例如,我们可能希望将日志消息写入磁盘的脚本仅接收严重错误,而不是在警告或信息日志消息上浪费磁盘空间。
我们正在使用fanout交换,它不会给我们太多的灵活性 - 它只能进行无意识的广播。
我们将使用direct交换。direct交换背后的路由算法很简单 - 消息进入队列,其 binding key与routing key完全匹配。
为了说明这一点,请考虑以下设置:
在此设置中,我们可以看到direct交换X与两个绑定到它的队列。第一个队列绑定orange绑定,第二个绑定有两个绑定,一个绑定密钥为black,另一个绑定为green。
在这样的设置中,使用routing key orange发布到交换机的消息 将被路由到队列Q1。 routing key为black 或green的消息将转到Q2。所有其他消息将被丢弃。
使用相同的 binding key绑定多个队列是完全合法的。在我们的示例中,我们可以在X和Q1之间添加绑定键black的绑定。在这种情况下,直接交换将表现得像fanout一样,并将消息广播到所有匹配的队列。路由键为black的消息将传送到 Q1和Q2。
接收消息将像上一个教程一样工作,但有一个例外 - 我们将为我们感兴趣的每个严重性创建一个新的绑定。
result = channel.queue_declare(queue='', exclusive=True)
queue_name = result.method.queue
for severity in severities:
channel.queue_bind(exchange='direct_logs',
queue=queue_name,
routing_key=severity)
下面通过Code 加深理解。
消息发布订阅Client_direct.py
import pika
import time
credentials = pika.PlainCredentials('xiaoxia', 'xiaoxia')
connection = pika.BlockingConnection(pika.ConnectionParameters(
'47.244.28.93', 5672, '/', credentials))
# 声明queue
channel = connection.channel()
channel.exchange_declare(exchange='round_robin_queue_mmmm',
exchange_type='direct')
# n RabbitMQ a message can never be sent directly to the queue, it always needs to go through an exchange.
n = 20
sum = 0
counter = 1
rounting_keyName='routing_key_test1'
while counter <= n:
channel.basic_publish(exchange='round_robin_queue_mmmm', #Producer只能发送到exchange,它是不能直接发送到queue的,发送到默认exchange
routing_key=rounting_keyName, #路由key发送指定队列
body='Hello World:'+str(counter)) #发送的消息
counter += 1
print(" [x] Sent 'Hello World!'")
connection.close()
消息发布订阅Server_direct.py
消息发布订阅Server_direct1.py
import pika
import time
credentials = pika.PlainCredentials('xiaoxia', 'xiaoxia')
#建立连接
connection = pika.BlockingConnection(pika.ConnectionParameters(
'47.244.28.93', 5672, '/', credentials))
channel = connection.channel()
channel.exchange_declare(exchange='round_robin_queue_mmmm', exchange_type='direct')
result = channel.queue_declare(queue='', exclusive=True)
queue_name = result.method.queue
rounting_keyName='routing_key_test1'
channel.queue_bind(exchange='round_robin_queue_mmmm',
queue=queue_name,
routing_key=rounting_keyName)
print(' [*] Waiting for logs. To exit press CTRL+C')
print(' [*] queue_name:'+queue_name)
def callback(ch, method, properties, body): #定义回调函数用于取出队列中的数据
print(" [x] Received %r" % body)
time.sleep(1)
ch.basic_ack(delivery_tag=method.delivery_tag)
channel.basic_consume(queue=queue_name,
on_message_callback=callback) #不确认消息
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming() #监听数据
消息发布订阅Server_direct1.py
import pika
# 在这种模式下,RabbitMQ会默认把p发的消息依次分发给各个消费者(c),跟负载均衡差不多
credentials = pika.PlainCredentials('xiaoxia', 'xiaoxia')
# 建立连接
connection = pika.BlockingConnection(pika.ConnectionParameters(
'47.244.28.93', 5672, '/', credentials))
channel = connection.channel()
channel.exchange_declare(exchange='round_robin_queue_mmmm', exchange_type='direct')
result = channel.queue_declare(queue='', exclusive=True)
queue_name = result.method.queue
rounting_keyName = 'routing_key_test11'
channel.queue_bind(exchange='round_robin_queue_mmmm',
queue=queue_name,
routing_key=rounting_keyName)
print(' [*] Waiting for logs. To exit press CTRL+C')
print(' [*] queue_name:' + queue_name)
def callback(ch, method, properties, body): # 定义回调函数用于取出队列中的数据
print(" [x] Received %r" % body)
time.sleep(1)
ch.basic_ack(delivery_tag=method.delivery_tag)
channel.basic_consume(queue=queue_name,
on_message_callback=callback) # 不确认消息
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming() # 监听数据
可以看到 消息发布订阅Server_direct.py 消息发布订阅Server_direct1.py在direct模式下,唯一的区别就是routing_key 不同,一个能够接收到数据,一个不能够接收。从而达到了filter过滤的目的