用于微服务通信的 HTTP 与消息传递

Posted 小小怪物

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用于微服务通信的 HTTP 与消息传递相关的知识,希望对你有一定的参考价值。

微服务架构最近作为一种创建复杂且可扩展的软件系统的技术而广受欢迎。微服务是可扩展、可独立部署的服务,可通过网络相互通信。

使这些服务更容易相互通信是微服务设计的主要问题之一。HTTP 和消息传递是微服务通信的两种常用方法。

用于Web服务器和客户端之间通信的通用协议称为HTTP(超文本传输协议)。HTTP 经常用作微服务体系结构中服务之间的通信方式。

另一方面,消息传递涉及使用消息传递系统(如RabbitMQ,Apache Kafka或Amazon SQS)的服务之间的消息交换。

HTTP 和消息传递之间的决策取决于许多变量,包括特定用例、可伸缩性要求和系统复杂性。两种协议都有优点和缺点。在这种情况下,了解每种策略的优缺点对于选择最佳行动方案至关重要。

对于微服务通信,本文将研究 HTTP 和消息传递之间的区别,并概述每种策略所涉及的权衡。

使用 HTTP 进行通信

HTTP是万维网的基础,广泛用于Web浏览器和服务器之间的通信。近年来,它也被用作微服务之间的通信手段。在此技术中,RESTful API 用于跨微服务交换数据。

让我们看一些代码,观察微服务中基于 HTTP 的通信与基于消息传递的通信有何不同:

public class OrderService 

   

    private RestTemplate restTemplate;

   

    public OrderService(RestTemplate restTemplate)

        this.restTemplate = restTemplate;

    

   

    public void processOrder(Order order)

        Customer customer = restTemplate.getForObject("http://customer-service/customers/" + order.getCustomerId(), Customer.class);

        // process order logic...

    

1

在此示例中,订单微服务向客户微服务发出 HTTP 请求,以使用 .使用该函数检索客户数据,并将响应反序列化为 Customer 对象。RestTemplategetForObject

我们有两个微服务,一个客户微服务和一个订单微服务。订单微服务可能会通过客户微服务的 RESTful API 获取客户端信息。

基于 HTTP 的通信的好处

  • 易于使用:HTTP是一种众所周知的简单协议。开发人员可以轻松创建 RESTful API 来公开微服务并启用它们之间的通信。
  • 无状态:由于其状态,HTTP自然是可扩展的。每个请求都是单独处理的,客户端和服务器之间不需要连接。
  • 缓存:HTTP允许缓存,这在处理大量数据时很重要。微服务可以通过缓存频繁请求的数据来减少系统负载并提高速度。

基于 HTTP 的通信的缺点

  • 延迟:交换大量数据时,基于 HTTP 的连接可能会产生延迟。这可能会导致反应时间变慢和性能降低。
  • 复杂性:随着端点和方法数量的增加,RESTful API 可能会变得复杂。这会使系统维护和更新变得困难。
  • 缺乏可靠性:基于 HTTP 的通信依赖于网络,可能会受到网络缓慢和错误的影响。

通过消息传递进行通信

消息代理用于在基于消息传递的通信中促进微服务之间的通信。消息在微服务之间的队列中路由,从而分离发件人和收件人。

在此示例中,我们有两个相同的微服务:

  1. 客户微服务
  2. 订购微服务

一旦客户微服务将此信息发布到消息代理,订单微服务就会订阅此信息。

客户微服务标识符

public class CustomerService

   

    private MessageBroker messageBroker;

   

    public CustomerService(MessageBroker messageBroker) 

  

        this.messageBroker = messageBroker;

        

   

         public void createCustomer(Customer customer)

        // create customer logic...

        messageBroker.publish("customer.created", customer);

      

 
 

订购微服务代码

public class OrderService 

   

    private MessageBroker messageBroker;

   

    public OrderService(MessageBroker messageBroker)

        this.messageBroker = messageBroker;

        this.messageBroker.subscribe("customer.created", this::processOrder);

    

   

    private void processOrder(Customer customer)

        // process order logic...

    

1

建立新客户后,客户微服务会将客户信息发布到消息代理。订单微服务使用 subscribe 方法订阅此信息,并在收到新的客户端信息时调用该方法。processOrder

基于消息传递的通信的好处

  • 可扩展性:基于消息传递的通信具有极强的可扩展性,能够处理大量数据,几乎没有延迟。这使其非常适合高通量应用。
  • 可靠性:由于使用了消息代理,基于消息传递的通信非常可靠。通信在正确处理之前会排队,从而减少数据丢失的可能性。
  • 适应性:基于消息传递的通信具有适应性,可以处理广泛的数据形式,包括二进制数据。因此,它适用于处理复杂数据结构的应用程序。

基于消息传递的通信的缺点

  • 复杂性:基于消息传递的通信可能难以设置和管理,尤其是在涉及大量消息代理时。
  • 协议支持有限:基于消息传递的通信通常仅限于少数协议,例如 AMQP 或 MQTT。这可能会使与使用其他协议的其他系统的集成成为问题。
  • 缺乏标准化:目前没有用于微服务通信的通用消息协议,这使得各种系统之间的互操作性存在问题。

与示例中一样,微服务中基于 HTTP 的通信和基于消息的通信之间存在很大差异。基于 HTTP 的通信简单易用,但随着端点和方法数量的增加,它可能会造成延迟和复杂性。

尽管基于消息传递的通信具有令人难以置信的可扩展性和可靠性,但设置和操作更加复杂。最终,这两种方法之间的选择取决于应用程序的特定要求。

结论

HTTP 和消息传递对于微服务通信有其优点和缺点。HTTP 是一种更直接、更完善的协议,使其更容易实现并与现有基础架构集成。它还提供了与负载均衡器和代理的更好兼容性,使其成为需要高可用性和可扩展性的系统的理想选择。

另一方面,消息传递为微服务提供了更强大、更灵活的通信机制。它允许异步和解耦通信,这对于需要松散耦合和事件驱动架构的系统是有益的。

消息传递还支持不同的模式,例如发布/订阅,这有助于降低复杂性并提高可伸缩性。

最终,HTTP 和消息传递之间的选择将取决于微服务体系结构的特定要求。团队在决定通信协议时应仔细考虑可伸缩性、灵活性和兼容性等因素。

在许多情况下,结合 HTTP 和消息传递优势的混合方法可能是最有效的解决方案。

异步消息传递和微服务

【中文标题】异步消息传递和微服务【英文标题】:Asynchronous Message-Passing and Microservices 【发布时间】:2018-07-15 10:31:09 【问题描述】:

我正在计划开发一个基于微服务的架构应用程序,我在阅读 Ronnie Mitra 的《微服务架构》一书时决定使用 kafka 进行内部通信;马特麦克拉蒂;迈克·阿蒙森; Irakli Nadareishvili 他们说:

让微服务直接与消息代理交互(例如 RabbitMQ 等)很少是一个好主意。如果两个微服务是 通过消息队列通道直接通信,他们共享一个 数据空间(通道),我们已经详细讨论过 两个微服务共享一个数据空间的弊端。相反,我们 可以做的是将消息传递封装在一个独立的后面 可以提供消息传递能力的微服务,在一个松散的 耦合方式,连接到所有感兴趣的微服务。

我使用 Netflix Eureka 进行服务注册和发现,Zuul 作为边缘服务器和 Hystrix。 这么说,在实践中,我该如何实现那种微服务呢?如何使我的微服务独立于通信通道(在本例中为 Kafka)? 实际上我直接与频道交互,所以我的发布者/订阅者和 kafka 之间没有额外的层。

2018 年 6 月 2 日更新

更准确地说,我们有几个微服务:一个是发布关于某个主题的新闻(activemq、kafka...),另一个微服务订阅该主题并对传入的消息进行一些操作.所以我们有这些服务耦合到消息代理(到通道)......我们在我们的代码中“嵌入”了消息代理的 api,例如,如果我们想更改消息代理,我们必须更改所有使用消息代理 API 的微服务。因此,他们建议使用作为各种消息的“调度程序”的微服务(在图片中我假设是事件中心)。这样,它是唯一与通道交互的组件。

【问题讨论】:

你能解释一下“如果两个微服务通过消息队列通道直接通信,它们共享一个数据空间(通道)” @techagrammer 我更新了问题。 【参考方案1】:

在服务架构中,使您的代码不受通信渠道限制的正确方法是对自给自足的消息进行适当建模。历史性的例子是文档模式下的 WSDL、EDIFACT、HATEOAS 等。从这个角度来看,使用 spring-boot 和 kafka 的微服务只是大型机统治世界以来相同旧事物的不同实现。

基本上,如果您将应用视为黑盒异步服务器;应用程序所做的一切都是接收事件并产生新事件。在应用程序中如何引发事件应该无关紧要。 Http 请求、jms 消息中的 xml、kafka 中的 json 等等 - 所有这些都只是传递事件的一种方式,应用程序的业务层应该只响应事件的内容。

因此,业务层通常围绕一些作为有效负载交付的自定义模型/域构建。业务层由与通信通道(kafka 侦听器、http 侦听器等)对话的侦听器/生产者层调用/触发。除了记录和执行安全性之外,您不应该在应用程序中使用通信通道逻辑。我已经看到了由原始 jms 连接或解析请求的 url 驱动的业务逻辑的不幸示例。如果您的代码中有此内容,则说明您未能正确构建代码。

但是说起来容易做起来难。有些人擅长这个级别的建模,有些人永远学不会。

除了尝试和失败,别无他法。

【讨论】:

【参考方案2】:

一般前言 - 如果您不需要,请不要这样做。如果您正在处理大量事件和事件备份问题等,那么引入队列系统可能是一个很大的改进。但是如果您没有遇到任何问题,您可能最好使用较低复杂性的直接服务通信。

回到你的问题 - 听起来你想抽象你与队列的通信,因为你担心用不同的系统替换队列 - 这是正确的吗?

在这种情况下,您可以按照您的建议进行 - 在中间开发一项新服务。这伴随着物理服务的所有包袱(包括部署、扩展等)。

或者第二种选择是编写一个客户端库,以您想要的方式抽象队列,并允许您在需要参与队列的所有服务中重用它。这样,您不必为此目的物理部署另一个服务,但您仍然可以完全控制您的队列接口应该是什么样子,并且您有一段代码来合并更改(至少朝着队列)。如果您确定库的面向应用程序的一面足够稳定,这将起作用。

但是,当您不确定是否需要所有复杂性时,不要在第一次迭代中执行任何这些操作。 (过度工程是一件危险的事情)

【讨论】:

+1 用于在通信通道上引入包装器,它提供了在 JMS 之间切换的灵活性。【参考方案3】:

您应该创建一个接口,比如说“队列”,它提供您想要从 Kafka 或 RabbitMQ 获得的所有功能,即创建差异。类似 Queue 接口的 KafkaQueue 和 RabbitMQQueue 的 impl,并注入您想要在系统中使用的正确 impl。

如果你使用新的队列系统,你现有的代码不会改变

在这种情况下,创建另一个微服务是额外的开销

【讨论】:

以上是关于用于微服务通信的 HTTP 与消息传递的主要内容,如果未能解决你的问题,请参考以下文章

Redis、Kafka或RabbitMQ:哪个作为微服务消息代理最合适?

微服务是不是可以结合 REST 和消息传递?

Kafka 和 REST 用于微服务之间的通信?

使用消息传递的微服务和 SOA

微服务解决的四大问题

微服务系列微服务注册与发现