为什么是兔子?什么是MQ?它如何改进我们的应用程序?我为什么要了解更多呢?-这些是我第一次被介绍给RabbitMQ时问的问题。我是Gabor,现在是RabbitMQ的工程师和顾问。在我使用RabbitMQ的时间里,我了解到即使是有经验的客户也会问这些问题。
在我们深入研究RabbitMQ是什么以及如何使用它之前,有必要更多地了解问题域本身。不同服务(即计算机)之间的通信是一个由来已久的问题。
一方面,有定义交通工具和通信属性的不同协议。此类协议的一些示例包括SMTP、FTP、HTTP或WebSockets(仅举几例),它们都基于TCP/UDP。它们处理消息的格式化、可靠性和找到正确的收件人。
另一方面,我们可以从信息的角度来探讨交际。它存在于一个系统中,然后被传输到另一个系统,得到转换,也就是说,它有一个生命周期。当它从一个系统传输到另一个系统时,我们应该知道消息在哪里,以及在任何给定的时间点谁拥有它。
上面提到的通信协议可以确保消息的所有权(和“物理”位置)从一个系统转移到另一个系统(尽管执行该事务可能需要一些时间)。在双方都在场的情况下,我们可以认为这次转让是双方之间的交易。大多数情况下,这种主动交换是可取的,例如,询问服务的状态并期望得到及时和准确的答复。现实世界中的一个例子是通过电话呼叫某人:1)我们开始通话,2)等待对方应答,3)进行愉快的讨论,4)挂断电话。
但也有其他时候,我们不需要答案,我们只需要接收者取得消息的所有权并履行其职责。在这种情况下,我们需要一个中介代理,即另一个系统来(临时)取得消息的所有权,并确保消息到达其目的地。为了进一步说明电话示例,对方目前无法接听,因此我们留下语音留言。语音邮件服务将通知目标接收者。
这种异步(延迟的)消息传递是RabbitMQ提供的。显然,它可以做的不仅仅是一台简单的答录机,所以让我们看看下面它提供的一些选项。
(如果您有兴趣了解更多有关RabbitMQ的历史,我推荐Alvaro Videla和Jason Williams的“RabbitMQ在行动”的第一章。它将揭示为什么它以兔子的名字命名的答案)。
RabbitMQ是一个免费、开源且可扩展的消息队列解决方案。它是一种理解AMQP(高级消息队列协议)的Message Broker,但也能够与其他流行的消息传递解决方案(如MQTT)一起使用。它具有高可用性、容错性和可扩展性。它是在Erlang OTP中实现的,这是一项专为构建STATBE、可靠、容错和高度可扩展的系统而量身定做的技术,这些系统具有处理大量并发操作的本地能力,例如RabbitMQ和其他系统,如WhatsApp、MongooseIM等等。
在非常高的级别上,它是一个中间件层,它使应用程序中的不同服务能够相互通信,而无需担心消息丢失,同时提供不同的服务质量(QoS)要求。它还支持细粒度和高效的消息路由,从而实现应用程序的广泛解耦。
为了展示RabbitMQ的多功能性,我们将使用三个案例研究来演示RabbitMQ如何非常适合作为黑盒托管服务方法,作为与支持功能良好的微服务体系结构的应用程序紧密集成的方法,或者作为其他遗留项目的门户。
当一个整体系统被分解成独立的子系统时,需要解决的最大问题之一是使用哪种通信技术。像MuleSoft或MassTransport这样的解决方案可以通过声明HTTP侦听器和发送器来“连接”服务。这种解决方案将RabbitMQ视为黑盒,但仍然能够利用RabbitMQ的功能。作为直接通信的示例,让我们使用HTTP“连接”各个服务。虽然它是一个得到很好支持和可靠的选择,但它也有一些缺点:1)没有解决服务发现问题。一种可能的解决方案是使用DNS。随着系统的扩展和增长,查找和平衡此负载的复杂性也随之增加。RabbitMQ可以减轻解决方案增加的复杂性。2)交流是短暂的。消息很容易在网络层被丢弃或复制。如果服务暂时不可用,则传递失败。
RabbitMQ通过使用消息队列作为一种传输方式,可以在这两种情况下提供帮助。服务可以发布和使用消息,这将端到端消息传递与目标服务的可用性分离。如果消费服务暂时不可用,与HTTP不同的是,消息被安全地缓冲并保留在RabbitMQ中,并最终在服务恢复在线时交付。
可发现性也得到了简化。我们只需要知道RabbitMQ在哪里以及队列名称是什么。虽然这看起来只是重新创造了问题,但这是可伸缩的。队列名称充当服务的地址。单个服务使用队列中的消息提供了一种可伸缩性的方法,即每个队列可以服务于多个使用者并平衡负载。不需要更改已内置于服务中的队列配置。
这种适度静态的队列配置将RabbitMQ推向中间件层,在中间件层,可靠的设计可以保证长期稳定的服务质量。
在光谱的另一端是一种更加流畅的体系结构,它适应了许多微服务不断变化的需求。RabbitMQ之所以在这个环境中大放异彩,是因为它提供了非常强大的路由功能。
路由逻辑以不同的(所谓的)交换类型实现,这些交换类型可以在需要时由应用动态创建。目的地服务创建它们希望从中消费的队列,然后通过指定发布者在发布消息时可以使用的键的模式将它们绑定到交换。(将这些键视为交换可以用来将消息路由和传递到一个或多个队列的元数据。)。
RabbitMQ提供了四种有用的交换类型,涵盖了大多数消息传递用例:1)直接交换。这将把传入消息传递到其绑定键与消息的路由键完全匹配的任何队列。如果使用队列名称作为路由关键字绑定队列,则可以将其视为一对一消息传递。通过使用多个队列的绑定键将同一消息传递到多个队列非常简单。2)主题交流。这将把传入消息传递到通配符绑定关键字与发布消息的路由关键字匹配的任何队列。绑定密钥可以包含复合路由密钥的通配符匹配条件。(例如,绑定密钥logs.*.error将与路由密钥logs.counting.error和logs.ui.error匹配)。这使我们能够编写逻辑包含良好的简单服务,并且消息将通过RabbitMQ的“魔力”到达正确的服务。3)扇出交换。有些消息需要传送到所有队列,这是可以使用扇出交换而不是在应用程序中编写复杂的多播逻辑的地方。使用RabbitMQ扇出交换,每个服务都将适当的队列绑定到交换,而不需要指定绑定键,这一切都是自动发生的。如果指定了绑定密钥,扇出交换机将简单地忽略它,并且仍然将消息路由/广播到绑定到它的所有队列。4)报头交换。该交换利用了AMQP消息的结构,并且能够基于AMQP消息的报头(包括自定义报头)进行复杂的路由。标头是附加到通过AMQP发送的每封邮件的元数据。
除了交换之外,RabbitMQ中还有其他有用的特性,可以实现非常复杂的消息传递逻辑。一些最重要的功能包括:1)自定义插件。RabbitMQ允许用户添加插件,因此是可扩展的。RabbitMQ几乎每个方面都是可定制的,包括管理、身份验证和授权、备份解决方案和集群。2)聚类。当单个RabbitMQ服务器不够用时,可以连接多个RabbitMQ代理来协同工作并扩展系统。它可以使RabbitMQ处理更多消息或提高对错误的恢复能力。3)服务质量调整。通过将TTL(生存时间)值附加到消息或队列,可以帮助传递对时间敏感的消息。超时消息可以自动传递到死信队列。将普通路由逻辑和这些额外功能相结合可以产生高度高级的路由逻辑。另一个有用的功能是使用优先级队列,发布者可以在其中为每条消息分配优先级。还可以限制未确认消息的数量,这允许消费服务的性能调优,在这种情况下,RabbitMQ应用了背压机制。
在前面的用例中,我提到了使用插件扩展RabbitMQ功能的可能性。这个强大的特性允许RabbitMQ充当RabbitMQ原生(支持AMQP)服务和其他遗留应用程序之间的中介层。一些值得注意的例子包括:1)通过简单地启用插件,将RabbitMQ用作MQTT代理。这为许多物联网技术打开了新的天地。2)RabbitMQ的JMS(Java Message Service)插件,该插件允许RabbitMQ与任何支持JMS的消息传递解决方案进行通信。3)如果您的应用程序使用专有协议进行通信,则可以开发一个自定义插件来连接任何此类服务。
如上面的示例所示,RabbitMQ几乎没有什么不能与之通信的。但就像生活中的任何事情一样,这是有代价的。尽管配置RabbitMQ大部分都很简单,但有时仅有的功能数量可能会让人望而却步。如果您在设计、实施或支持RabbitMQ经纪人方面遇到任何问题,请联系我们的专家团队。
想要一个直观的系统来轻松监控和维护RabbitMQ吗?现在就获得您的免费45天试用的WOBATOAM。
回到博客