再看rabbitmq的交换器和队列的关系

最近又要用到rabbitmq,业务上要求服务器只发一次消息,需要多个客户端都去单独消费。但我们知道rabbitmq的机制里,每个队列里的消息只能消费一次,所以客户端要单独消费信息,就必须得每个客户端单独监听一个queue。所以我最终想实现的是服务端只声明exchange,客户端来创建queue和绑定exchange。但是在看各种rabbitmq博文和讨论的时候,我觉得对exchange的模式和queue间的关系讲的都不是很清楚。所以我决定自己验证一下

fanout模式和direct模式

本文主要验证fanout模式和direct模式下以上猜想是否可行。fanout模式就是大名鼎鼎的广播模式了,只要queue绑定了fanout的交换器,就可以直接的收到消息,无需routingkey的参与。而direct模式就是通过routing key直接发送到绑定了同样routing key的队列中。那么,在这两种exchange的模式下,是否都可以实现服务端仅创建exchange,客户端创建queue并绑定exchange呢?

Direct模式验证

我们先把交换器、routingkey、队列的名称定义好:

交换器为directTest

routingkey为direct_routing_key

队列测试3个,首先测试Direct_test_queue_1,再行测试Direct_test_queue_2,再行测试Direct_test_queue_3

代码使用spring boot框架快速搭建。我们先规划好需要几个类来完成这个事情:

针对生产者,需要RabbitmqConfig,用来配置exchange的

针对生产者,需要DirectRabbitSender,用来实现Direct模式的消息发送

针对消费者,需要DirectConsumerOne,来测试第一个队列Direct_test_queue_1生成和消息接收

针对消费者,需要DirectConsumerTwo,来测试第二个队列Direct_test_queue_2生成和消息接收

针对消费者,需要DirectConsumerThree,来测试第三个队列Direct_test_queue_3生成和消息接收

我们还需要一个测试类RabbitmqApplicationTests,用于测试消息的发送和接收

rabbitmq先配置一个DirectExchange

@Bean DirectExchange directExchange(){ return new DirectExchange("directTest", true, false); }

我们可以看到Direct交换器的名称定义为了directTest,这时候还未绑定任何的队列。启动程序,若我们的设想没错,则rabbitmq中应该已经生成了directTest的exchange。

再看rabbitmq的交换器和队列的关系


Bingo!directTest交换器成功创建。接下来,我们去编写DirectRabbitSender的代码

@Component public class DirectRabbitSender{ @Autowired private RabbitTemplate rabbitTemplate; private final String EXCHANGE_NAME = "directTest"; private final String ROUTING_KEY = "direct_routing_key"; public void send(Object message) { rabbitTemplate.convertAndSend(EXCHANGE_NAME, ROUTING_KEY, message); } }

我们可以看到代码中,通过rabbitTemplate发送消息到了交换器为directTest,routingkey为direct_routing_key的地方。但这时候我们没有任何队列了,自然接不到消息。现在我们去编写第一个消费者DirectConsumerOne来接受消息。

@Component @RabbitListener(bindings = @QueueBinding( value = @Queue(value = "Direct_test_queue_1", durable = "true"), exchange = @Exchange(value = "directTest"), key = "direct_routing_key" )) public class DirectConsumerOne { @RabbitHandler private void onMessage(String message){ System.out.println("监听队列Direct_test_queue_1接到消息" + message); } }

通过代码可以看到,我们通过@QueueBinding把Direct_test_queue_1队列绑定到了directTest和direct_routing_key上。Direct_test_queue_1并没有在rabbitmq创建,这并没有关系。一般来说,@RabbitListener会自动去创建队列。启动程序,我们去看一下rabbitmq里队列是不是创建了。

再看rabbitmq的交换器和队列的关系

Bingo!再次验证成功。我们去看看绑定关系是不是正确。这时候Direct_test_queue_1应该绑定到了名为directTest的交换器,而绑定的routingkey为direct_routing_key

再看rabbitmq的交换器和队列的关系

biubiubiu!绑定关系完全正确。到了这里,我们进行最后一步,写了单元测试去发送消息,查看控制台中消费者是否成功收到消息。RabbitmqApplicationTests的代码如下:

@SpringBootTest class RabbitmqApplicationTests { @Autowired private DirectRabbitSender directRabbitSender; @Test void contextLoads() { } @Test public void directSendTest(){ directRabbitSender.send("direct-sender"); directRabbitSender.send("direct-sender_test"); } }

启动测试类,然后去查看控制台。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyddsf.html