消息的路由模式
https://www.jianshu.com/p/e87a467e4d56
RabbitMQ提供了四種交換器,分別是
Direct交換器、Fanout交換器、Topic交換器、Headers交換器
注:
交換機,接收發送到RabbitMQ中的消息並決定把他們投遞到那個隊列的組件。
這裏的交換器決定了消息會投遞到哪一個隊列當中。
Direct(默認的隊列方式,完全匹配):把消息路由到那些binding key與routing key完全匹配的Queue中
-
通過路由鍵來進行交換器與隊列進行綁定
Fanout(一種廣播模式,不涉及路由):路由規則是把所有發送到該Exchange的消息路由到所有與它綁定的Queue中 -
不處理路由鍵,給所有綁定的隊列都發送
Topic(有條件的選擇路由,也是一種廣播模式):模糊匹配,通過通配符滿足一部分規則就可以傳送,其中注意的是有兩個字符 ‘星號’ 和#號,
其中 *號 用於匹配一個單詞,#號用於匹配多個單詞(可以是0個) -
根據route key 匹配隊列,可以是一對多的關係(這裏指定是匹配關係)
-
topic交換器會將消息路由至匹配路由至路由鍵的任一隊列中。(只會有一個隊列會接收到這個消息)
Headers(可以實現類似於topic的效果):它通過採用消息屬性中的headers表支持任意的路由策略。
- Headers通過source、object和action取代了路由鍵的作用。
- 這種使用方式通常使用在headers屬性中使用了非常巨大的表值,否則消息的發佈速率不會有很大提升。
- 這種方式也可以結合一致性hash算法對header-type進行hash運算後實現加權負載均衡式的消息投遞。
在實際的項目中,通常在生產者定義的時候將交換器與隊列進行綁定
這裏以Topic方式爲例
/**
* @author Gjing
**/@Configurationpublic class RabbitMqConfiguration {
/**
* 聲明一個名爲topic.message1的隊列
*/
@Bean
public Queue topicQueue() {
return new Queue("topic.message1");
}
/**
* 聲明一個名爲topic.message2的隊列
*/
@Bean
public Queue topicQueue2() {
return new Queue("topic.message2");
}
/**
* 聲明一個名爲exchange的交換機
*
*/
@Bean
public TopicExchange exchange() {
return new TopicExchange("exchange");
}
/**
* 將topic.message1的隊列綁定到exchange交換機
*/
@Bean
public Binding bindMessage1() {
return BindingBuilder.bind(topicQueue()).to(exchange()).with("topic.message1");
}
/**
* 將topic.message2的隊列綁定到exchange交換機
*/
@Bean
public Binding bindMessage2() {
return BindingBuilder.bind(topicQueue2()).to(exchange()).with("topic.message2");
}}
發佈端
- this.rabbitTemplate.convertAndSend(交換器,路由鍵,消息)
- topic模式中匹配的在聲明隊列時指定的路由鍵new Queue(“topic.message2”)
/**
* @author Gjing
**/@Componentpublic class TopicProducer {
@Resource
private AmqpTemplate rabbitTemplate;
public void send() {
String message1 = "I am topic.message1";
String message2 = "I am topic.message2";
this.rabbitTemplate.convertAndSend("exchange", "topic.*", message1);
this.rabbitTemplate.convertAndSend("exchange", "topic.*", message2);
}}
消費端
- 消費者消費的是監聽一個或者多個隊列中的消息
- 這裏的消費端會消費隊列“topic.message2”中的消息
/**
* @author Gjing
**/@Component@Slf4jpublic class TopicConusmer2 {
@RabbitListener(queues = "topic.message2")
public void receive(String message) {
log.info("消費者2收到消息:{}", message);
}}