在上一篇文章如何理解微服务架构中,回顾了微服务架构的优缺点。在使用这种架构构建的应用程序中,服务之间的交互可能是一个挑战。有不同的方法可以实现这种交互。在这篇文章中,审查了同步交互(HTTP/HTTPS)。


同步微服务交互

#yyds干货盘点#——如何实现微服务之间的同步交互_数据库

      让我们回顾一下上面提供的示例。在这种情况下,我们有一个Database per Service模式。这意味着服务不共享数据库。他们每个人都有自己的数据库(数据库)或根本没有数据库。


同步微服务交互示例

用户访问酒店预订网站并选择入住日期。该酒店服务仅返回最小的可能酒店房间信息的列表。之后,用户选择特定的酒店房间。因此,我们将酒店房间和入住日期作为输入。预计将返回完整的酒店信息:

  • 酒店总结。例如,名称、地址、评级、描述、可用服务、房间描述等。酒店服务使用自己的数据库来获取所需的数据。
  • 酒店附近的景点。它可以是餐厅、剧院、电影院、博物馆等任何地方。这些信息通常不会改变。因此,它可以保存在酒店景点服务的数据库中。
  • 酒店附近的活动。这些是不时发生的事件。第三方 活动服务可用于获取入住期间酒店附近的活动(如节日、音乐会、展览等)。

总而言之,响应包含来自与HTTP/HTTPS同步通信的三个不同服务的数据。


同步微服务模式

乍一看,从酒店服务到酒店景点服务,从酒店景点服务到第三方活动服务,似乎就够了。但是,这种微服务交互方法存在常见问题。


服务发现

第一个问题是 酒店服务无法直接调用酒店景点服务(我们无法对服务 URL 进行硬编码)。为了提供稳定的服务工作,同一个服务的多个实例应该并行运行。实例的数量可以根据负载增加或减少,不健康的实例被健康的实例替换。因此,一些基础设施组件应该负责活动服务及其活动健康实例的列表。服务发现用于此目的。有关运行服务实例的信息保存在Service Registry 中。

例如,在Spring堆栈中它是Eureka。


客户端负载均衡

使用Service注册的第一个选项是客户端负载均衡

这是什么意思?我们有注册Service,其中包含有关健康实例的信息。酒店 Service可以与注册Service交互以查找有关酒店 Attractions Service 的活动服务实例,并使用某种算法来选择要使用的实例(例如循环)。

对所选服务实例执行调用。

在Spring 中,它通常是Ribbon。


网关

使用注册Service的第二个选项是使用网关(在初始图片中显示)。

在这种情况下,一个特殊的组件负责将请求重定向到所需的服务实例。Gateway与Service Registry一起工作以了解可以使用哪些服务及其实例。

它可以像这样工作:

  • 用户(个人或其他服务)调用例如 GET 
  • 酒店景点路径讲述了服务。
  • 网关查找有关酒店景点服务的信息。
  • 找到正在运行的酒店景点服务实例的URL 。
  • 例如,循环用于选择一个实例并发出请求。

在Spring 中,它通常是Zuul。


断路器

让我们回顾一下同步微服务交互的另一个问题。

在我们的示例中,将执行下一个请求序列:

  • 酒店服务部向酒店景点服务部提出请求。
  • 酒店景点服务向第三方活动服务提出请求。

如您所见,请求依赖于三个服务。此外, 第三方活动服务不在我们的控制范围内。

当其中一项服务缓慢时会发生什么?它如何影响整个应用程序?

问题在于,即使是一项服务的问题也会对整个系统的性能产生负面影响。

想象一下,当第三方事件服务关闭时的情况。在这种情况下,用户甚至看不到旅馆房间信息。是的,第三方活动服务提供的有关酒店附近活动的信息 对某些人来说可能很重要。然而,这并不重要。如果没有这些信息,人们仍然可以预订酒店房间。

当第三方事件服务性能不佳时,情况会更糟 。

想象下一个场景:

  • 向酒店服务部提出要求。
  • 请求是从酒店服务到酒店景点服务提出的。
  • 请求是从酒店景点服务到第三方活动服务。
  • 第三方事件服务在 30 秒内响应。

因此:

  • 酒店 Attractions Service阻塞线程以等待来自第三方事件服务的响应。
  • 酒店 Service阻塞线程以等待来自酒店 Attractions Service的响应。

在单个请求的情况下,不会发生非常严重的事情:用户只需等待大约 30 秒的响应。

但是,这里有两个主要问题:

  • 不是每个用户都会等待 30 秒。
  • 这些关于酒店附近活动的信息并不重要。

当我们查看真实情况时,情况变得更糟:来自用户的请求不止一个。许多用户正在寻找酒店房间。

这意味着这 30 秒的等待会对整个系统的性能产生负面影响:

  • 酒店景点服务的资源已耗尽。
  • 酒店服务更等待酒店景点服务的响应。
  • 酒店服务资源耗尽。
  • 该酒店服务无法事件过程与不使用既不是酒店房间列表的请求,酒店旅游服务,也不第三方活动服务。

解决方法很简单。使用断路器。

  • 为每个请求设置超时。
  • 如果在超时发生之前另一个服务没有收到来自一个服务的响应,则初始服务以默认值响应。
  • 在某些配置的时间段内,不会向有问题的服务发出请求。始终使用默认响应。
  • 一段时间后,将再次向相关服务发出请求。

再来看看第三方活动服务出现问题时的情况(酒店景点服务同样适用)。

  • 在酒店服务,使一个请求酒店旅游服务。
  • 该酒店景点服务使一个请求第三方事件服务,并等待1秒的响应。
  • 如果收到成功的响应,则一切正常。用户接收所有数据。
  • 如果响应不成功,用户将不会收到有关事件的信息。后续请求(例如接下来的 5 秒)将跳过对有问题的第三方事件服务的调用。

在Spring 中,它通常是Hystrix。


缓存

为了优化性能特征,在某些情况下可以使用缓存。

如果可能,它可以用于以下原因:

  • 跳过对目标服务的调用。
  • 如果目标服务出现问题,可以将一些默认(可能已过时或不准确)的数据返回给用户。

然而,缓存失效在这里可能是一个真正的挑战。


总结

在本文中,回顾了同步微服务交互的各种挑战。这种方法在某些情况下是适用的。但是,还有另一种微服务通信方式。异步微服务交互将在下一篇文章中回顾。