RabbitMq Direct exchange路由模型

官网就是最好的文档

上一篇文章RabbitMq Publish/Subscribe消息发布订阅模式 消息发布订阅模式中,就是通过广播来实现分发的。所有的customer都能够收到全部的消息。实际业务场景是需要filter的,怎么办?

我们将为其添加一个功能 - 我们将只能订阅一部分消息。例如,我们只能将关键错误消息定向到日志文件(以节省磁盘空间),同时仍然能够在控制台上打印所有日志消息。

Bindings

在前面的例子中,我们已经创建了绑定。您可能会记得以下代码:

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交换只是忽略了它的价值。

Direct exchange

我们希望扩展以允许根据消息的严重性过滤消息。例如,我们可能希望将日志消息写入磁盘的脚本仅接收严重错误,而不是在警告或信息日志消息上浪费磁盘空间。
我们正在使用fanout交换,它不会给我们太多的灵活性 - 它只能进行无意识的广播。

我们将使用direct交换。direct交换背后的路由算法很简单 - 消息进入队列,其 binding key与routing key完全匹配。

为了说明这一点,请考虑以下设置:
在这里插入图片描述
在此设置中,我们可以看到direct交换X与两个绑定到它的队列。第一个队列绑定orange绑定,第二个绑定有两个绑定,一个绑定密钥为black,另一个绑定为green。

在这样的设置中,使用routing key orange发布到交换机的消息 将被路由到队列Q1。 routing key为black 或green的消息将转到Q2。所有其他消息将被丢弃。

Multiple bindings
在这里插入图片描述

使用相同的 binding key绑定多个队列是完全合法的。在我们的示例中,我们可以在X和Q1之间添加绑定键black的绑定。在这种情况下,直接交换将表现得像fanout一样,并将消息广播到所有匹配的队列。路由键为black的消息将传送到 Q1和Q2。

Subscribing

接收消息将像上一个教程一样工作,但有一个例外 - 我们将为我们感兴趣的每个严重性创建一个新的绑定。

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过滤的目的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章