微服务异步响应

时间:2019-10-09 14:39:33

标签: spring-boot rabbitmq microservices

我遇到了很多博客,他们说,由于Rabbitmq具有异步特性,因此使用Rabbitmq可以提高微服务的性能。

在那种情况下,我不明白http响应是如何发送给最终用户的,我在下面更清楚地阐述我的问题。

  1. 用户向microservice1(面向用户的服务)发送http请求

  2. microservice1将其发送到Rabbitmq,因为它需要来自microservice2的某些服务

  3. microservice2接收请求处理,然后将响应发送给rabbitmq

  4. microservice1收到Rabbitmq的响应

现在如何将此响应发送到浏览器? microservice1是否等待直到收到来自Rabbitmq的响应? 如果是,那么它如何变得异步?

4 个答案:

答案 0 :(得分:1)

这是一个好问题。要回答这个问题,您必须想象服务器一次运行一个线程。通过RestTemplate向微服务发出请求是一个阻塞请求。用户单击网页上的按钮,这将触发您在microservice1中的spring-boot方法。在这种方法中,您向microservice2发出请求,然后microservice1进行阻塞等待响应。

该线程正忙于等待微服务2完成请求。线程并不昂贵,但是在非常繁忙的服务器上,线程可能是一个限制因素。

RabbitMQ允许微服务1将消息排队到微服务2,然后释放线程。当microservice2处理该消息并提供响应时,系统将触发您的接收消息(spring-boot / RabbitMQ)。同时,线程池中的该线程可用于处理其他用户的请求。当RabbitMQ响应到来时,线程池使用未使用的线程来处理请求的其余部分。

有效地,您正在使运行microservice1的服务器有更多时间可用的更多线程。仅在服务器负载沉重时才成为问题。

答案 1 :(得分:0)

您还可以使用事件源和CQRS并使整个流程异步。在这种情况下,微服务1创建一个代表用户请求的事件,然后立即将请求的已创建响应返回给用户。然后,您可以在请求完成处理时稍后通知用户。

我推荐Ben Stopford所写的《设计事件驱动系统》一书。

答案 2 :(得分:0)

好问题,让我们一一讨论

同步行为:

  • 客户端发送HTTP或任何请求,然后等待响应HTTP。

异步行为:

客户端发送请求,套接字上还有另一个线程在等待响应。响应到达后,就会通知原始发送者(通常使用类似回调的结构)。

现在我们可以讨论阻塞呼叫与非阻塞呼叫

当您使用Spring Rest时,每个调用将启动新线程并等待响应并阻塞您的网络,而无阻塞调用将使所有通过单线程和回推的调用返回响应而不会阻塞网络。

现在问您的问题

  

由于以下原因,使用rabbitmq改善了微服务的性能   Rabbitmq的异步特性。

,性能取决于您的TPS命中率和Rabbitmq不会提高性能。

消息传递为您提供了两种不同类型的消息传递模型

  • 同步消息传递
  • 异步消息传递

使用消息传递,您将获得松散的耦合和容错能力。

  • 如果您的应用程序需要阻止呼叫,例如需要响应,否则无法移动,请使用Rest
  • 如果您可以在没有响应的情况下工作,请在不阻塞的情况下进行
  • 如果您希望将应用程序设计为松散的,则可以使用消息传递。

总之,最重要的是要如何构建应用程序的体系结构样式,性能取决于可伸缩性。

您可以将应用程序与其余功能和消息传递结合起来,而将非阻塞性与消息传递结合起来。

在您的场景中,微服务1可能会使用rest模板或Web客户端和/或消息传递队列进行rest阻止调用,给其他API调用,一旦获得响应,就会将rest json调用返回给您的Web应用。

答案 3 :(得分:0)

我将再看看您的架构。通常,对于微服务-尤其是必须基本同步的面向用户的服务,ServiceA必须调用ServiceB(这反过来可以调用{{ 1}}等)返回响应。这种情况表明这些服务紧密耦合,从而使其变得脆弱。例如:如果ServiceC出现故障或在您的示例中过载,则ServiceB也会由于没有故障而脱机。因此,可能会发生以下一种或多种情况:

  • 将相关服务部署在包围整个域的立面后面-让客户端与立面同步交互,并让立面处理与幕后的多种服务的通话。
  • ServiceA中添加/更改数据时,使用MQTT或AMQP发布数据,并让ServiceB订阅以获取所需的数据,这样它就可以满足用户请求而无需显式调用其他服务< / li>
  • 考虑将ServiceAServiceA合并到一个可以处理请求而无需进行外部调用的服务中

您还可以将HTTP请求从客户端发送到服务,将应用程序状态设置为ServiceB或类似的文件,并让使用中的应用程序订阅waitingeventSuccess来自总线的集成消息。这个想法的主要目的是让菊花链式服务(再次,我不喜欢)轮流使用,而无论“完成”哪项服务,工作都会发布集成事件,以使正在收听的任何人都知道。您甚至可以执行以下操作:在初始请求中传递webhook URI,以使服务在完成后直接调用该应用程序(或使用SignalR或gRPC或...)

我们使用RabbitMQ的方式是实时集成服务,以便每个服务始终拥有自己需要响应的信息。以您的示例为例,在我们的世界中,eventFail在数据更改时发布事件。 ServiceB只关心并订阅这些事件的一小部分(通常仅是事件数据中的一个或两个),但是ServiceA更改后几秒钟(通常更少)就知道了,它具有响应请求所需的所有信息。每个服务从字面上不知道还有什么其他服务,它只是知道它关心的事件(并且符合合同)是不时发生的,因此需要注意它们。