一、什么是Exchange
首先我們要了解到,RabbitMQ 是 AMQP(高級消息隊列協議)的標准實現:
從 AMQP 協議可以看出,Queue、Exchange 和 Binding 構成了 AMQP 協議的核心
-
Producer:消息生產者,即投遞消息的程序。
-
Broker:消息隊列服務器實體。
-
Exchange:消息交換機,它指定消息按什么規則,路由到哪個隊列。
-
Binding:綁定,它的作用就是把 Exchange 和 Queue 按照路由規則綁定起來。
-
Queue:消息隊列載體,每個消息都會被投入到一個或多個隊列。
-
-
Consumer:消息消費者,即接受消息的程序。
二、Exchange的作用
Exchange的主要作用還是為了解耦。
AMQP 協議中的核心思想就是生產者和消費者的解耦,生產者不直接將消息投遞給隊列,而是將消息投遞給Exchange,然后Exchange根據相應的路由規則投遞給隊列,最后隊列將消息投遞到消費者。
舉個生活中的例子,不是很恰當,但大概意思就是這樣。將報紙、投遞站、投遞員、訂閱報紙的用戶分別看做生產者、exchange、隊列以及消費者。
報紙印刷后,會分發到投遞站,投遞站相當於exchange,會指定分發規則,例如,這一片區的報紙分給某個投遞員,投遞員拿到這些報紙后,對訂閱了該報紙的這一片區的用戶進行投遞。
當然這個隊則有多種,例如將區域看做一個規則、將報紙種類看做規則、或者區域加種類混合規則。下面就詳細介紹exchange的類型。
三、Exchange的類型
3.1 Fanout Exchange
這是最簡單的一種交換器,首先要知道一個概念-banding。banding是將exchange和隊列綁定的一種隊則,java中萬物皆對象,所以這個綁定也看做一個對象。
banding中還有個路由鍵的概念。就是即使交換機與隊列進行了綁定,但是在某些場景下,我們不希望與交換機綁定的隊列都能收到消息。所以就可以去指定一個路由鍵。
在進行綁定的時候去指定路由鍵,在發送消息的時候指定Exchange、指定路由鍵,才可以正確的將消息發送到隊列上。
Fanout Exchange 比較特殊 會忽略路由鍵的設置,直接將 Message 廣播到所有綁定的 Queue 中。
3.2 Direct Exchange
Direct Exchange 是RabbitMq的模式模式,將Exchange和隊列綁定的時候,需要指定路由鍵,並且在發消息的時候也需要指定路由鍵,並且路由鍵必須要完全一致。
例如指定了路由鍵是green,那么只有與exchange綁定並且路由鍵為green的隊列才會收到消息。
3.3 Topic Exchange
與Direct Exchange基本相同,唯一區別在於路由鍵。Topic exchange 的路由鍵可以去進行模糊匹配。
* 表示一個單詞的模糊匹配 例如,路由鍵是 *.apple.big 則表示第一個單詞可以是任意的,只要后邊單詞完全匹配,就可以。
# 表示完全模糊匹配。例如 路由鍵是 #.little ,那么 發送消息的路由鍵可以是 green,apple,little,也就是說前面的單詞是任意的。
四、Exchange的使用
多說無益,直接擼代碼。
就用topic 做演示,其他的模式基本一樣。
1. 首先設定一個路由鍵
public static final String TOPIC_C = "red.*.*";
2.配置一個topicExchange
@Bean public TopicExchange topicExchange() { return new TopicExchange(EXCHANGE_C); }
3. 配置一個隊列
第一個參數拜師隊列名稱,第二個參數表示是否持久化
@Bean public Queue queueC() { return new Queue(QUEUE_C, false); //隊列持久 }
4. 配置bangding
@Bean public Binding bindingC() { return BindingBuilder.bind(queueC()).to(topicExchange()).with(TOPIS_C); }
5. 發送消息代碼
第一個參數是Exchange名稱,第二個參數是路由鍵,第三個參數是內容,第四個參數是唯一性id
如果是 Fanout Exchange 那么就不用指定路由鍵傳參為null,
如果是 Direct Exchange,那么路由鍵就要與指定的路由鍵完全匹配。
public void sendMsg(String content) { CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString()); rabbitTemplate.convertAndSend(EXCHANGE_C, "red.cc.dd", content, correlationId); }
這樣路由鍵是 red.*.* ,發送消息的路由鍵是 "red.cc.dd" ,並且因為是Topic Exchange模式,所以該路由鍵是可以匹配到的。
完整代碼請參考:https://github.com/zhuanzhiBUG/springboot-rabbitmq.git
部分參考內容:https://blog.csdn.net/y4x5M0nivSrJaY3X92c/article/details/80416996