-
这个疑问主要是最近在学springcloud的stream时,消息发送端配置rabbitmq去找交换机,接收端还是去找同一个交换机。交换机这么重要么,消息队列不应该时找队列啊?
-
还有一个疑问是,翻笔记的时候发现,入门案例队列的定义是放发送端,而在后面是放在消费端,交换机在接收端和发送端都有定义,属实看一个问题发现一坨问题,越看越萌了。
在这之前可以先回顾一下一些重要概念:包括 bindingKey、RoutingKey、channel等,可以参考下面这个博文:
rabbitMq的组件与原理,exchange四种方式,重复消费、顺序错乱_rabbitmq 生产者 消费者 exchange相同-CSDN博客
下面介绍一些整个流程:
在rabbitmq刚入门时,是没有注明exchange的,使用默认交换机。
在发送消息时:
Provider:定义连接到MQserver的信道channel,定义队列queue,使用默认交换机往指定队列发送消息
Consumer:定义连接到MQserver的信道channel,往定义好的队列中获取消息
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());//Provider
channel.basicConsume(QUEUE_NAME, true, deliverCallback, cancelCallback);//Consumer
消息生产者并没有直接将消息发送给消息队列,而是通过建立与Exchange的Channel,将消息发送给Exchange,Exchange根据规则,将消息转发给指定的消息队列。消费者通过建立与消息队列相连的Channel,从消息队列中获取消息。有了交换机,就不一样了:
在发送消息时:
Provider:定义连接到MQserver的信道channel,定义指定类型的交换机exchange(例如direct),往交换机中发送消息并制定routingkey(不指定具体的队列)
Consumer:定义连接到MQserver的信道channel,定义指定类型的交换机exchange(如果与上面的生产者的一致则对接成功),定义队列queue,将交换机与队列进行绑定binding,并制定bindingkey。
message:发送的消息按routingkey找到bindingkey对应的队列,Consumer进行消费。
channel.basicPublish(EXCHANGE_NAME, bindingKey, null, message.getBytes("UTF-8"));//Provider
channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {})//Consumer
消费者和生产者两端都有信道channel,但是连接两者的(交换机+队列)都是绑定好的。找到消费端找到交换机,就说明找到组织了,因为队列相对来说没有那么重要,很多时候都可以使用临时队列(没有名字的)。
这里还有一个误区:连接消费者和生产者(交换机+队列)只有一组,一条消息可以被被转发到不同的交换机,一个交换机可以绑定多个队列(fanout),一个队列也可以绑定多个交换机,一个队列可以被多个消费者消费(消息确认机制,竞争关系),一个消费者也可以接收多个队列的消息,队列内的消息不会被消费两次,但是同一个消费者理论上可以消费多次同样的一条消息。