什么是 RabbitMQ?
在任何云原生应用中,微服务必须通信才能获得响应用户所需的所有信息。 应确保即使组件之间出现网络问题或故障,此消息传递也仍然可靠。 RabbitMQ 是一种可以用来提高消息传递可靠性的工具。
在户外设备零售店中,你正在通过微服务取得快速发展。 但是,在应用程序测试中,从一个微服务到另一个微服务的某些调用似乎丢失了。 你想要确保此问题不会出现在关系到公司声誉的生产环境中。
在本单元中,你将了解 RabbitMQ 如何为微服务创建灵活且可复原的通信平台。
为何要在云原生应用中使用消息中转站?
云原生应用由独立的微服务组成,通常由不同的团队生成并使用不同的技术和语言。 每个团队都有自己的开发冲刺和升级计划,并可能不断部署修复和新功能。 但是,当用户发出请求时,接收该请求的微服务几乎始终需要调用其他微服务和支持服务并接收它们的回复以构建完整的响应。
显然,这些服务间请求和响应的格式和模式必须由开发团队达成一致,并且很少改变。 它们通常以 REST API 的形式实现。 应该优先实现每个接口的新功能,而不改变现有的方法和参数。 但是,如果你选择让微服务直接通信,则可能会出现以下几个问题:
- 当目标微服务脱机或繁忙时,发送给它的消息会发生什么情况? 消息丢失会造成哪种后果?
- 如何将同一条消息发送到多个目标?
- 如果一个微服务在多个容器上运行,应该向哪个容器发送消息?
消息中转站是解决这些问题的中间件。 服务将消息发送到消息中转站而不是直接发送到目标。 中转站按照消息的到达顺序将其存储在队列中。 目标服务订阅这些队列并逐个接收消息进行处理。
如果目标服务不可用,发送微服务仍可以将消息放入队列中。 当目标重启时,它会继续从队列中的同一位置获取消息。 虽然发送方必须等待更长时间,但不会丢失任何消息。
由于多个目标可以订阅一个队列,因此一条消息可由多个微服务接收。 此外,当多个容器托管单个微服务的实例时,第一个可用的实例将获取该消息。 中转站自动将消息分发到实例以分散负载。
什么是 RabbitMQ?
RabbitMQ 是最流行的消息中转站之一,具有许多功能,使其成为处理云原生应用通信的理想选择。 其中包括:
- 托管队列的 RabbitMQ 服务器。 该服务器支持群集和故障转移,以实现高可用性,并可在容器中运行。
- 高级消息队列协议 (AMQP)、简单文本导向的消息协议 (STOMP) 和消息队列遥测传输 (MQTT) 的实现。
- 可以在 .NET、Java 和 Erlang 中使用的 AMQP 客户端库。
RabbitMQ 的概念
在 RabbitMQ 术语中,发送和接收消息的微服务是客户端。 发送消息的客户端称为消息生成者。 接收消息的客户端称为消息使用者。 RabbitMQ 服务是消息中转站。
如何发送消息
RabbitMQ 功能多样,能够实现许多不同的排队模型。 让我们了解一些流行的模式。
如果你有一个生成者和一个使用者,则可以使用一个队列,所有消息都会到达同一目标。 即使在这种简单的配置中,也可以构建一个能够顺利处理中断的可靠消息系统:
向竞争使用者发送消息
在竞争使用者模型中,生成者向单个工作队列发送消息。 两个或更多个使用者从队列中检索消息。 使用者竞争检索消息,因为每条消息只能由一个使用者检索。
在多个容器上托管一个使用方微服务来提升容量时,此模式在云原生应用中很有用。 每条消息只会到达使用者的一个实例,因此只会处理一次。 工作不会重复。
发布和订阅
如果你要将一条消息从一个生成者发送给多个使用者,请使用发布/订阅模型。 生成者将消息发送到交换区。 每个使用者订阅来自该交换区的消息。 当使用者订阅时,RabbitMQ 会为该订阅创建新的工作队列。 每条消息将复制到该交换区的每个队列,并由每个订阅的使用者接收。 使用者不会竞争每条消息。 相反,他们都会收到每条消息的副本。
发布/订阅模型使用扇出交换,将每条消息复制到每个工作队列。
当你希望每条消息由多个微服务处理时,此模式很有用。 例如,当客户为购物篮结帐时,你可能想要发送一条有关他们购买的每件产品数量的消息。 该消息应同时到达发货微服务以指示仓库打包包裹,并到达库存微服务以减少库存数量并可能向供应商触发订单。
路由消息和主题
有时你想要将单个消息分发到多个使用者,但对于每个使用者,都应用一个筛选器。 此模式称为消息路由器。 与发布/订阅模型一样,使用者订阅交换以创建多个工作队列。 不过,该模型使用直接交换,而不是扇出交换。 通过此交换,每个订阅都有一个绑定密钥。 只有路由键与绑定键匹配的消息才会发送到此订阅。 其他消息将被筛选掉。
当某些使用者只需要处理消息流的子集时,此模式很有用。 例如,假设你有一个在发生错误时发送消息的微服务。 所有错误都应发送到日志记录微服务。 应将严重错误发送到管理微服务,以便警报工程师解决问题。
直接交换根据单个条件路由消息。 为了进一步灵活解决问题,可以使用主题交换。 对于每条消息,可以使用一个路由键,其中的多个字词以点分隔。 在绑定键中,可以使用通配符 * 来替代一个单词,或使用 # 来替代零个或多个单词。
注意
RabbitMQ 的替代方案包括 Apache Kafka 和 Azure 服务总线。 这两个消息中转站都由 .NET Aspire 中的专用组件支持。 此学习路径的后续模块将介绍 Azure 服务总线。