RabbitMq交換機類型介紹
在RabbitMq中,生產者的消息都是通過交換器來接收,然后再從交換器分發到不同的隊列,再由消費者從隊列獲取消息。這種模式也被成為“發布/訂閱”。
分發的過程中交換器類型會影響分發的邏輯。
- 直連交換機:Direct exchange
- 扇形交換機:Fanout exchange
- 主題交換機:Topic exchange
- 首部交換機:Headers exchange
1 DirectExchange(直連交換機)
? 直連交換機是一種帶路由功能的交換機,交換機會通過路由(Routing_key)和指定隊列進行綁定。在創建的時候會創建一個路由
,和一個綁定關系
,路由和綁定關系相互對應。
? 發送消息時會指定exchange和routing_key,所有通過該routing_key和exchange綁定的隊列都會收到同樣的消息。
測試實例在https://blog.csdn.net/qq_43331014/article/details/132255631文章中作為例子詳細講解過了。
2 Topic exchange(主題交換機)
? 在RabbitMq中,生產者的消息都是通過交換機來接收,然后再從交換機分發到不同的隊列中去,在分發的過程中交換機類型會影響分發的邏輯,下面主要講解一下主題交換機。
? 主題交換機核心是可以以范圍的行為向隊列發送消息,它和直連交換機區別在于,直連交換機一個隊列通過一個binding_key和交換機的進行綁定,只能接受一中消息;主題交換機可以按照一定的匹配規則去匹配多個routing_key
。
那匹配規則是什么?
交換機和隊列的binding_key
需要采用*.#.*.....
的格式,每個單詞用.
作為分隔符,其中:
*
表示一個單詞(必須出現的)#
#(井號)用來表示任意數量單詞(零個或多個)
例如:假設有一條消息的routing_key
為topic.china.shanghai
,另一條為topic.china
,那么binding_key
為topic.#
的隊列這兩條消息都會收到
通配符 | 功能 | 示例 |
---|---|---|
\* | 匹配一個單詞 | topic.* 可以匹配到 topic.china 或者 topic.shanghai 等 |
# | 匹配零個或多個單詞 | topic.# 可以匹配到 topic.china 或者 topic.china.beijing |
通俗理解:
? 主題交換機的流程,相當于報紙訂閱。有一個總報社(相當于生產者)
發出各種類型的報紙到各個分報社,分報社相當于不同的交換機
,每種類型報紙相當于不同的routing_key
,再往下有賣報點去分報社去報紙,但每個賣報點根據消費者的需求所需要的類型不一樣。比如一個分報社手里有兩種類型的報紙:新聞.經濟
、新聞.體育
。這時三個賣報點來取報紙,賣家A只需要新聞經濟類
,那他跟交換機的binding_key就是新聞.經濟
;賣家B只需要新聞體育類
,那他的binding_key就是新聞.體育
;而賣家C這很多消費者都在他這買報紙,他既需要新聞經濟類
又需要新聞體育類
,他的binding_key相當于是新聞.#
,新聞下面的都收。
? 而直連交換機是什么,相當于更小的分銷商,針對更精確的人群。他不能像上面那種情況把新聞下所有類都收了,只能一對一的關系,有人需要新聞.經濟
就綁定上,只去收新聞.經濟
報,不能多拿,再有人需要新聞.體育
才能再收體育報。
下面通過代碼演示下主題交換機
-
創建交換機、隊列、綁定關系
@Configuration public class TopicRabbitConfig {@Beanpublic Queue firstQueue(){return new Queue("topic.shanghai",true,false,false);}@Beanpublic Queue secondQueue(){return new Queue("topic.beijing",true,false,false);}@Beanpublic Queue thirdQueue(){return new Queue("topic.china.beijing",true,false,false);}@Beanpublic TopicExchange topicExchange(){return new TopicExchange("topicExchange",true,false);}/*** 交換機和隊列綁定,并設置綁定key*/@BeanBinding firstBinding(){return BindingBuilder.bind(firstQueue()).to(topicExchange()).with("topic.shanghai");}@BeanBinding secondBinding(){//只要是消息攜帶的路由鍵是以topic.開頭,后面還更有一個單詞的都會分發到該隊列return BindingBuilder.bind(secondQueue()).to(topicExchange()).with("topic.*");}@BeanBinding thirdBinding(){//只要是消息攜帶的路由鍵是以topic.開頭,都會分發到該隊列return BindingBuilder.bind(thirdQueue()).to(topicExchange()).with("topic.#");} }
可以看到已經創建成功
-
分別給交換機按三個不同routing_key發送消息,對應的routing_key分別為:
topic.shanghai
、topic.haha.hehe
、topic.test
@PostMapping("/sendMessageByTopic") public AjaxResult sendMessageByTopic(@RequestBody Map params) {String id = UUID.randomUUID().toString();String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));params.put("messageId",id);params.put("createTime",createTime);/*** 發給交換機,通過匹配隊列和交換機綁定關系值,判斷發送給哪個隊列*/rabbitTemplate.convertAndSend("topicExchange","topic.shanghai",params);rabbitTemplate.convertAndSend("topicExchange","topic.haha.hehe",params);rabbitTemplate.convertAndSend("topicExchange","topic.test",params);return AjaxResult.success("成功"); }
三個隊列分別對應的匹配規則及接受到消息的結果如圖:
可以看到
topic.shanghai
隊列只能匹配一條,topic.china.beijing
隊列因為binding_key是topic.#
所以全部匹配,topic.beijing
隊列因為binding_key是topic.*
,所以匹配了topic后面只跟一個單詞的。
監聽就不細說了,跟交換機類型關系不大,主要根據隊列名稱去監聽,實例可以看https://blog.csdn.net/qq_43331014/article/details/132255631第六節
3 Fanout exchange(扇形交換機)
扇形交換機是廣播消息
,會將接到的消息發送到每一個與其綁定的隊列中去。
不需要管綁定的binding_key
是什么
在編寫發送消息代碼時,不需要填寫routing_key
/***廣播交換機* @return* @throws InterruptedException*/
@PostMapping("/sendMessageByFanout")
public AjaxResult sendMessageByFanout(@RequestBody Map params) {String id = UUID.randomUUID().toString();String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));params.put("messageId",id);params.put("createTime",createTime);/*** 扇形交換機,不需要指定路由,會廣播給每一個綁定的隊列*/rabbitTemplate.convertAndSend("fanoutExchange","",params);return AjaxResult.success("成功");
}
4 Headers exchange(首部交換機)
? 與routingKey無關,匹配機制是匹配消息頭中的屬性信息。在綁定消息隊列與交換機之前聲明一個map鍵值對,通過這個map對象實現消息隊列和交換機的綁定。當消息發送到RabbitMQ時會取到該消息的headers與Exchange綁定時指定的鍵值對進行匹配;如果完全匹配則消息會路由到該隊列,否則不會路由到該隊列。
匹配規則x-match有下列兩種類型:
x-match = all :表示所有的鍵值對都匹配才能接受到消息
x-match = any :表示只要有鍵值對匹配就能接受到消息
種交換器類型在性能上相對來說較差,在實際工作中很少會用到。