微服务通信。为什么应该切换到消息队列。

2025-06-07

微服务通信。为什么应该切换到消息队列。

这实际上是我在这里写的一条旧评论的更详细版本。

在实施微服务时,一个相当关键的设计要点是:我的服务之间应该如何通信?
许​​多人通常选择设计一些 RESTful HTTP API,每个服务对外暴露,然后让其他服务使用普通的 HTTP 客户端调用它。
这样做有一些优点,主要是可以通过 DNS 解析和 API 网关轻松发现服务,但它也有很多缺点。
例如,如果被调用的服务崩溃了,无法响应怎么办?你的客户端服务必须实现某种重新连接或故障转移逻辑,否则,你将面临丢失请求和信息的风险。云架构应该具有弹性,能够从故障中优雅地恢复。此外,HTTP 请求是一个阻塞 API,使其异步意味着在客户端需要一些巧妙的技巧。

进入消息队列

在处理多个相互通信的服务时,使用消息队列实际上是一种相当古老的解决方案。想想企业服务总线 (ESB) 或 Java JMS 规范之类的老方法。

首先介绍一些术语:

  • 消息:信息的封装,通常由两部分组成。一部分是包含元数据的键值对,另一部分是包含实际消息本身的二进制包。
  • 生产者:创建并发送消息的人
  • 消费者:接收并阅读消息的人
  • 队列:将消息放入队列以便稍后由一个或多个消费者检索的通信通道
  • 交换:一个队列聚合器,它抽象出消息队列并根据一些预定义的逻辑将消息路由到适当的队列。

消息队列架构需要一项名为消息代理的附加服务,其任务是收集、路由并将消息从发送者分发到正确的接收者。

可以将其想象成邮件服务。您(生产者)正在向某人(消费者)发送一封信件(您的消息),您可以通过指定地址(消息的路由逻辑,例如发布消息的主题)并将信件交给当地邮局(消息代理)来实现。信件投递后,您无需再负责确保它是否真正到达您的朋友手中。邮局会处理此事。

在微服务环境中,它实际上是一个非常可靠的解决方案,因为它在松散耦合的服务之间添加了一个抽象层(消息代理本身),并允许完全异步通信。

错误难免会发生。与其简单地逃避,不如积极应对。

请记住,云环境应该具备容错能力,服务必须能够优雅地故障,并且不会因为其中一个服务宕机而拖垮整个应用程序。使用消息队列,即使某个微服务意外宕机,代理仍然可以接收传入的消息,存储它们以供日后使用(以便宕机的服务恢复后可以恢复它们),并可以选择向其他服务发送“遗嘱”消息,告知接收者已宕机。此外,推送/拉取发布/订阅主题队列机制在设计服务间通信时提供了更大的灵活性和效率,而发送二进制有效负载的能力使得我们可以轻松地使用Google ProtoBuffMessagePack等格式来替代 JSON,这些格式在带宽使用方面更加高效。

安全是关键

像RabbitMQ这样的高级代理服务器支持多种消息协议(AMQP、MQTT、STOMP 等),拥有灵活的授权机制(访问控制、虚拟主机,甚至通过HTTPAMQP等多种传输协议支持第三方/自定义身份验证服务),并且基本上可以减轻您服务编排请求授权的负担。只需将自定义微服务插入 Rabbit 的身份验证后端,并在其中编写策略即可。剩下的工作将由代理服务器处理。

大规模基础设施

使用像 Rabbit 这样的代理程序的消息队列也有助于提高可扩展性,而可扩展性是微服务的另一个关键方面。
如果某个服务在负载下遇到困难,我们希望能够快速启动更多实例,而无需重新配置。使用 HTTP 作为通信方式时,我们通常会有一个自注册的服务发现服务器(例如Netflix Eureka或容器编排系统,例如KubernetesRancher),并集成某种负载均衡器,以便将流量分发并路由到各个实例。使用消息队列时,我们的代理程序本身就是负载均衡器。如果多个消费者同时监听某个主题,消息将按照配置的策略进行投递(更多关于 RabbitMQ 的 QoS 信息,请点击此处)。

例如,我们可以让四个服务实例以轮询方式处理消息,但由于 QoS 参数在运行时是可自定义的,因此如果某个消费者完成工作的时间过长,我们需要平衡负载,我们也可以切换到公平调度策略。另外,请注意,客户端配置完全在运行时完成(顺便说一下,交换机、队列和主题声明也是如此),因此无需修改代理的配置或重新启动任何东西。

异步==效率

我们在一开始就提到,与 HTTP 请求相比,消息的一个关键特性是它允许完全异步通信。如果我需要向另一个服务发出请求,我可以在其主题上发送一条消息,然后继续我的工作。我可以在我自己的主题上收到响应时处理它,而无需等待。关联 ID用于跟踪哪条响应消息对应哪个请求。这与我们之前提到的弹性一致。
在 HTTP 场景中,如果我发出请求,而被调用方已断开连接,连接将被拒绝,我必须不断尝试,直到它恢复连接。
使用消息系统,我可以发送请求,然后就不管它了。如果被调用方无法接收,代理会将消息保留在队列中,然后在消费者重新连接时将其投递。我的响应会在可以接收时返回,我无需阻塞或等待它。

总而言之,留言很棒。表达一​​些爱意吧。

这绝不是对 HTTP 的抱怨(HTTP 仍然很棒,特别是对于公共前端 API),而是尝试引导您采用更高效、更熟练的策略来协调微服务通信,所有这些都可以通过开源软件、开放协议(如 AMQP)来实现,这些协议可以防止供应商锁定,并且具有低(且可扩展)的基础设施成本(请参阅RabbitMQ 的要求)。

我所有的微服务项目都使用了 RabbitMQ,体验非常棒。欢迎在评论区留言分享你的想法!你之前用过消息队列吗?你的使用体验如何?

文章来源:https://dev.to/matteojoliveau/microservices-communications-why-you-should-switch-to-message-queues--48ia
PREV
什么是 CSP?为何以及如何将其添加到您的网站。
NEXT
如何让输入字段随着输入而增大/缩小