为什么不仅在微服务之间使用异步消息

时间:2020-04-25 18:27:54

标签: multithreading web-services http asynchronous apache-kafka

为什么我们不只使用异步消息/事件作为微服务体系结构中的唯一通信方式,并删除所有sync / http调用?
我无法想象在任何情况下同步如何比异步具有优势。

想象一下以下三个服务A,B,C中的呼叫链:
UI-> A-> B-> C

  • UI调用A来请求一些数据。
  • A需要调用B以获得一些数据,然后它将返回UI进行处理。
  • 类似地,B需要调用C来获取一些数据。

想象一下,所有服务都有(有限)线程池来服务传入的请求。
A中已接受来自UI的连接请求的线程将向B发出HTTP请求。
由于对B的请求是IO的一种形式,因此该线程将被抢占,直到从A-> B-> C-> B-> A传输数据为止,从而浪费了很长时间。
其他服务也会发生类似的线程抢占。


如果我们有消息驱动的设计,则每个服务中都可以有以下线程池:

  • 一个仅运行kafka使用者的线程池来读取下游服务的响应。
  • 一个线程池,用于接受来自上游服务的新请求。

请考虑以下事件顺序:

  • A :: Thread1从UI获取请求,并生成消息“ MsgAB ”,其中将请求ID和核心数据封装到消息队列中。
  • A :: Thread1将请求连接对象插入到requestId -> requestObject的全局映射中。
  • A :: Thread1现在可以自由处理更多请求。
  • 类似地,B会为C产生味精。
  • C将创建一个响应消息,以供B读取,然后将产生 MsgBA
  • 现在,运行其中一个kafka使用者之一的A :: Thread2将使用 MsgBA 封装原始请求ID。
  • A :: Thread2将使用全局映射中的请求对象回复给UI。

这种设计的优势在于,线程是免费的,可立即增加服务的吞吐量,此外还具有消息驱动的体系结构的通常优势,例如可伸缩性和可扩展性(消息也可以通过日志,跟踪,数据分析来读取)或其他任何生产服务甚至不知道的服务。

要处理超时,我们可以采用以下策略:

  • 我们可以将所有请求ID保留在任何对时间敏感的数据结构中,从而可以快速访问和删除最旧的条目。 堆或LRU缓存(使用标准的DLL +哈希映射实现)可以是此数据结构的不错选择。
  • 我们可以让运行调度程序的专用线程遍历此数据结构,并向所有过期/超时的请求回复超时错误。

那么为什么基于HTTP的微服务架构如此流行?

0 个答案:

没有答案
相关问题