RabbitMQ 交換機詳解
1. 前言
Hello,大家好。本小節為大家介紹 RabbitMQ 中交換機的相關概念,以及交換機的構成及作用。在 RabbitMQ 消息發送原理概述小節中,我們已經對 RabbitMQ 整體架構有了一個初步的了解,已經知道了交換機在 RabbitMQ 中充當的角色,那么本節會繼續深入講解 RabbitMQ 中的交換機。
本節主要內容:
-
什么是交換機;
-
RabbitMQ 常用交換機詳解;
什么是交換機;
RabbitMQ 常用交換機詳解;
2. 什么是交換機 ?
在 RabbitMQ 中,交換機主要用來將生產者生產出來的消息,傳送到對應的頻道中,即交換機是一個消息傳送的媒介,其英文被稱為 exchange 。交換機在 RabbitMQ 中起著承上啟下的作用。
RabbitMQ 根據不同業務場景,為我們內置了多種交換機,但是這些交換機并不是每一種都會用到,常用的交換機也就 3 種,接下來讓我們看一下都有哪三種吧。
交換機名稱 | 類型 | 使用頻率 |
---|---|---|
直通交換機 | Direct | 高 |
扇形交換機 | Fanout | 高 |
主題交換機 | Topic | 高 |
3. RabbitMQ 常用交換機詳解
3.1 直通交換機
定義:
直通交換機,又被叫做直連交換機,即 Direct Exchange ,是可以直接將消息根據特定匹配規則發送到對應的消息隊列的交換機,如果匹配規則相同,則一條消息可以被發送到多個對應的消息隊列上,而這個匹配規則是通過 routing_key 來進行匹配。
偽代碼:
// 省略與 RabbitMQ 服務端建立連接的過程
String queueName = "test_direct_x";
channel.exchangeDeclare("direct_exchange", "direct");
channel.queueDeclare(queueName, true, false, false, null);
代碼解釋:
第 2 行,我們聲明了一個名為 test_direct_x 隊列名稱,對于直通交換機而言,這個名稱就是我們所說的 routing_key 。
第 3 行,我們使用了 channel 的 exchangeDeclare 方法來聲明了一個交換機,其中,該方法的第一個參數表示交換機的名稱,第二個參數則表示交換機的類型,這里我們將類型定義為了直連交換機類型,其類型名稱為 direct 。
第 4 行,我們使用了 channel 的 queueDeclare 方法來聲明了一個隊列,其中,該方法的第一個參數為我們聲明的 test_direct_x 隊列。
消息發送流程:
結合上述代碼,直通交換機的消息發送流程如下圖所示:
消息在經過 direct_exchange 交換機之后,會根據名為 test_direct_x 的 routing_key 與相應的消息隊列進行匹配,如果消息隊列 1 、消息隊列 2 、消息隊列 3 都與該 routing_key 相匹配,那么我們的消息會全部流轉到這三個消息隊列中去。
3.2 扇形交換機
定義:
扇形交換機,即 Fanout Exchange ,是通過類似廣播的形式,將消息傳遞到消息隊列中去,與直通交換機不同的是,扇形交換機不需要綁定 routing_key ,會將消息傳遞到所有與該交換機綁定的消息隊列中去。
偽代碼:
// 省略與 RabbitMQ 服務端建立連接的過程
String queueName = "test_fanout_x";
channel.exchangeDeclare("fanout_exchange", "fanout");
channel.queueBind(queueName, "fanout_exchange", "");
代碼解釋:
第 2 行,我們聲明了一個名為 test_fanout_x 隊列。
第 3 行,我們使用了 channel 的 exchangeDeclare 方法來聲明了一個交換機,其中,該方法的第一個參數表示交換機的名稱,第二個參數則表示交換機的類型,這里我們將類型定義為了扇形交換機類型,其類型名稱為 fanout 。
第 4 行,我們使用了 channel 的 queueBind 方法來將交換機與消息隊列進行綁定,其中,該方法的第一個參數為我們聲明的 test_fanout_x 隊列,第二個參數為要綁定的交換機的名稱,這里為 fanout_exchange ,對于扇形交換機來說,隊列和交換機的綁定是必須的,否則無法傳遞消息。
消息發送流程:
結合上述代碼,扇形交換機的消息發送流程如下圖所示:
消息在經過 fanout_exchange 交換機之后,會首先檢測有沒有已經與該交換機進行綁定的消息隊列,如果沒有與該交換機進行綁定的消息隊列,則消息會自動失效,且跑拋出異常;如果有與該交換進行綁定的消息隊列,則 fanout_exchange 交換機會將消息以廣播的形式傳遞到所有的消息隊列中去。
上圖中,消息隊列 1 、消息隊列 2 、消息隊列 3 這三個消息隊列的名稱均為 test_fanout_x ,且均與名為 fanout_exchange 的交換機進行了綁定,所以,消息在經 fanout_exchange 交換機之后,均會被傳遞到這三個隊列中去。
3.3 主題交換機
定義:
主題交換機,即 Topic Exchange ,是通過 routing_key 與 bidding_key 的匹配規則進行消息傳遞的一種交換機。
與直通交換機不同的是,直通交換機中的 routing_key 和 bidding_key 的名稱必須保持一致,但是在主題交換機中,bidding_key 會通過一定的規則去匹配 routing_key ,以此將消息發送到相匹配的消息隊列中去。
Tips: 交換機與隊列之間進行綁定的 key ,被稱為 bidding_key ,消息與交換機之間進行綁定的 key ,被稱為 routing_key 。
偽代碼:
// 省略與 RabbitMQ 服務端建立連接的過程
String queueName = "test.topic.x";
channel.exchangeDeclare("topic_exchange", "topic");
channel.queueBind(queueName, "fanout_exchange", "test.#");
代碼解釋:
第 2 行,我們聲明了一個名為 test.topic.x 的隊列。
第 3 行,我們使用了 channel 的 exchangeDeclare 方法來聲明了一個交換機,其中,該方法的第一個參數表示交換機的名稱,第二個參數則表示交換機的類型,這里我們將類型定義為了扇形交換機類型,其類型名稱為 topic 。
第 4 行,我們使用了 channel 的 queueBind 方法來將交換機與消息隊列進行綁定,其中,該方法的第一個參數為我們聲明的 test_fanout_x 隊列,第二個參數為要綁定的交換機的名稱,這里為 fanout_exchange ,第三個參數為 bidding_key , 這里是 test.# 。
消息發送流程:
結合上述代碼,主題交換機的消息發送流程如下圖所示:
消息在經過 topic_exchange 交換機之后,會根據 routing_key 與 bidding_key 的匹配規則檢索相匹配的消息隊列,如果沒有檢測到任何相匹配的消息隊列,則消息會自動失效;如果檢測到存在相匹配的消息隊列,則消息均會會被傳送到這些消息隊列中去。
上圖中,消息隊列 1 、消息隊列 2 是我們代碼所設置的,bidding_key 為 test.# 的兩個消息隊列,第三個消息隊列的 bidding_key 為 #.topic ,根據主題交換機 # 號匹配規則,routing_key 都會與這些 bidding_key 相匹配,消息均會被傳遞到這三個消息隊列中去。
Tips: 在主題交換機中,除了 # 號匹配規則之外,還有 . 號匹配規則,他們兩個的匹配規則大同小異,這里只對 # 好匹配規則做了介紹,希望同學們在課下可以自行了解 . 號的匹配規則。
4. 小結
本小節對常用的 3 種 RabbitMQ 中的交換機進行了詳細介紹,從不同種類交換機的概念開始,到交換機的偽代碼實現,再到不同種交換機的消息發送流程結束,為各位同學詳細介紹了直通交換機、扇形交換機、主題交換機的相關概念,以及消息發送流程,旨在幫助同學們可以對 RabbitMQ 中常用的 3 種交換機都有一個系統性地了解。