翻译自:https://gigi.nullneuron.net/gigilabs/rabbitmq-who-creates-the-queues-and-exchanges/
消息传递是任何分布式架构的一个基本组成部分。它允许生产者发送消息到任意数量的消费者,而无需了解他们。这是真正伟大的异步和解耦的通信。
上图展示了一个在你使用RabbitMQ时,非常基本但典型的架构。生产者发布一条消息到exchange。交换器使用路由策略发送消息到绑定的队列。举个例子,如果它是一个Fanout类型(广播)exchange,exchange会把每条消息复制一份然后分发给每个队列,每个消费者可以从队列读取消息并处理它们。
这个架构中生产者和消费者能正常工作的一个重要前提是,所有这些RabbitMQ基础设施(即队列、交换器和绑定关系)必须是已经存在的。生产者无法发布消息给一个不存在的exchange,也不可能有消费者从一个不存在的队列中获取消息。
因此,让生产者或消费者在发送和接收消息之前创建exchange、queue和bindings并不是不合理的,让我们来看一下具体如何实现,并且思考下每种方法的影响。
1、解耦
生产者和消费者完全解耦,理想情况下,生产者应该知道只知道exchange(而不是队列),并且消费者应该只知道队列(不是交换器),bindings是exchange和queue之前的胶水。
一个可行的方法是由生产者处理exchange的创建,然后消费者创造他们所需要的队列并将其绑定到exchange。这种分离策略的优点是,当消费者需要新队列时,消只需要根据需要创建队列并绑定,不需要生产者需要了解他们。这不是完全解耦,消费者必须知道exchange的存在以绑定它。
另一方面,有一个非常确实的危险。如果在消费者部署之前,有任意消费者正在运行,那么exchange就无法绑定,这样生产者启动后发出的所有消息都将丢失。这需要系统实际情况来决定是否是可接受的。
2. 生产者创建一切
生产者可以配置成在启动时创建所有必要的基础设施(交换器、队列和绑定)。这有一个好处,那就是消息将不会因为队列和交换器没有绑定而丢失(因为队列绑定到交换器不需要任何消费者先运行)。
然而,这意味着生产者必须知道所有的队列,这并不是一个解耦的方法。每次添加新队列,生产者必须重新配置和部署创建绑定它。
3. 消费者创建一切
相反的方法是让消费者在启动的时候创建一切。像前面的方法一样这种方法也存在耦合,因为消费者必须知道他们的队列和哪个交换器绑定。交换器的任何改变(例如重命名)都意味着所有消费者都必须重新配置和重新部署。这种复杂性可能会导致项目无法使用大量的队列和消费者。
4. 不创建任何东西
一个完全不同的选择是生产者和消费者不创建任何所需的基础设施。相应地,它事先创建使用的用户界面管理插件Management Plugin 和 Management CLI.。这样做有几个好处:
- 生产者和消费者可以真正的解耦。生产者只了解exchanges,消费者只知道队列。
- 这可以很容易地部署脚本和自动化通道。
- 任何更改(如新队列)可以直接添加,而不需要触及任何现有的,已经部署的生产者和消费者。
5. 总结
异步消息传递是一种非常棒的方式用于服务在分布式架构中的解耦,但让他们保持分离,需要一个有效的策略来维护底层消息传递结构(RabbitMQ的情况下,这些是队列、交流和绑定)。
如果让生产者和消费者服务自己管理创建他们所需要的exchange和队列,可能会有一些更沉重的代价,比如初始信息损失,耦合,和操作维护更复杂(消费者的配置和部署)。
最好的方法可能是:在程序外使用脚本配置。这可以确保服务保持分离,队列系统可以根据需要动态地改变,而不必影响很多现有的服务。