消息的路由模式
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);
}}