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過濾的目的

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