【问题标题】:How to handle network calls in Microservices architecture如何处理微服务架构中的网络调用
【发布时间】:2016-11-05 11:10:09
【问题描述】:

我们使用微服务架构,其中顶级服务用于向最终用户公开 REST API,后端服务负责查询数据库。

当我们收到 1 个用户请求时,我们会向后端服务发出约 3 万个请求。我们将 RxJava 用于顶级服务,因此所有 30K 请求都会并行执行。 我们正在使用 haproxy 在后端服务之间分配负载。 但是,当我们收到 3-5 个用户请求时,我们会收到网络连接异常、无路由到主机异常、套接字连接异常。

这种用例的最佳做法是什么?

【问题讨论】:

  • 我这方面经验很少,但是30k请求后端听起来太多了。
  • 似乎你被分布式计算的谬误击中:网络可靠,延迟为零,带宽无限等。读这听起来更像是一个分层架构,需要多层才能获得到数据。
  • 30k 请求意味着从后端请求至少 30,000 位信息(面向响应的数据)或推送到后端(记录数据)。您提供什么样的网站,需要针对单个用户请求进行大量数据移动?听起来架构和方法被破坏了,需要重新审视恕我直言......

标签: networking architecture rx-java haproxy microservices


【解决方案1】:

好吧,您最终遇到了经典的微服务混乱。这与您采用什么技术完全无关——问题在于您应用微服务概念的方式!

在这种架构中,服务相互调用是很自然的(最好是异步发生!!)。由于我对您的服务 API 知之甚少,因此我不得不对您的后端出了什么问题做出一些假设:

我假设用户向一项服务发出请求。该服务现在将(显然是同步的)查询另一个服务并接收您描述的这 30k 条记录。由于您可能需要了解更多关于这些记录的信息,因此您现在必须针对每条记录向第三个服务/端点发出另一个请求,以汇总您的前端所需的所有信息!

这表明你可能把bounded contexts 弄错了!分析部分就这么多。现在来解决:

您的 API 应该返回所有信息以及枚举它们的查询!有时这似乎与微服务模式指定的对数据/状态的隔离和权限的类型相矛盾 - 但仅在一个服务中隔离数据/状态是不可行的,因为这会导致您当前遇到的问题 - 所有其他服务必须每次都查询该数据才能将正确的数据返回到前端!但是,只要对数据/状态的权限明确,就可以复制它!

让我用一个例子来说明这一点:假设你有一个经典的商店系统。文章被分组。现在你可能会编写两个微服务——一个处理文章,一个处理组!你这样做是对的!您可能已经决定 group-service 将保存与分配给组的文章的关系!现在,如果前端想要显示组中的所有项目 - 会发生什么:组服务接收请求并在前端接收到的漂亮 JSON 数组中返回 30'000 个文章编号。这就是一切都向南的地方:前端现在必须查询文章服务以获取它从组服务收到的每篇文章!!! Aaand 你完蛋了!

现在有多种方法可以解决这个问题:一种是(如前所述)将文章信息复制到 group-service:所以每次使用 group-service 将文章分配到一个组时,它都必须读取该文章的所有信息形成文章服务并存储它以便能够使用 get-me-all-the-articles-in-group-x 查询返回它。这相当简单,但请记住,当它在文章服务中发生更改时,您需要更新此信息,否则您将提供来自组服务的陈旧数据。在这个用例和I suggest you read up on it 中,事件溯源可能是一个非常强大的工具!您还可以使用从一个服务(在本例中为文章服务)发送到您偏好的消息总线的简单消息,并让组服务侦听这些消息并做出反应。

另一个针对您的问题的非常简单的快速而简单的解决方案也可能只是在文章服务上提供一个新的 REST 端点,该端点采用文章 ID 数组并将信息返回给所有这些端点,这样会更快.这可能会很快解决您的问题。

在使用微服务的后端中,一个好的经验法则是希望这些跨服务调用的数量保持不变,这意味着跨越服务边界的调用数量永远不应与请求的数据量直接相关!我们密切监视由于通过我们的 API 发出的给定请求而进行了哪些服务调用,以跟踪哪些服务调用了哪些其他服务以及我们的性能瓶颈将在哪里出现或已经引起。每当我们检测到一个服务产生了很多(没有固定的阈值,但每次我看到 >4 我都会开始提问!)调用其他服务时,我们会调查为什么以及如何解决这个问题!有一些很棒的指标工具可以帮助您跨服务边界跟踪请求!

让我知道这是否有用,以及您实施的任何解决方案!

【讨论】:

  • 感谢您的详细解释。您所做的假设完美地描述了我们正在尝试做的事情,我想在这里添加更多细节,组服务使用 Elastic Search(查询灵活性)和文章服务使用 Cassandra 进行存储(大容量数据)。在文章服务中再创建一个 REST 端点来接受 id 的列表听起来是可行的,这样我们将减少文章服务调用的次数。但是 URL 有大小限制,我们不能将所有 30K id 传递给一个文章服务调用。请分享您对此的看法。
  • 哦,那就使用请求的HTTP正文吧! URI 是发送此类数据的错误位置! ?
  • 是的,我们可以这样做,但是这样我们将无法实现我们想要的并行性,即当我们收到 1 个组请求时,只有一个文章服务将处于活动状态,而其他文章服务实例什么也不做。我们可以在多个文章服务调用中发送固定数量的 id,而不是在一次调用中将所有 id 发送到文章服务。但是,这违反了您在回答中提到的经验法则。
  • 没错,但让我们退后一步:如果索引正确,从数据库中查询 30'000 条记录只需
  • 是的,对于典型的 REST 应用程序来说确实如此,但在我们的例子中,一个请求在 1 分钟的时间窗口内处理约 200 万条记录,会话持续至少 180 秒,所以我相信它的开销很大只有一篇文章服务。缓存这么多数据也不可行。我们能否在不牺牲并行性和性能的情况下以最少的网络调用实现微服务架构。
猜你喜欢
  • 2017-03-19
  • 2021-02-05
  • 1970-01-01
  • 2018-09-24
  • 2015-04-30
  • 1970-01-01
  • 2018-08-11
  • 2018-01-07
  • 2019-11-09
相关资源
最近更新 更多