【问题标题】:Microservices: Parallels computing without counters微服务:没有计数器的并行计算
【发布时间】:2023-03-04 20:49:01
【问题描述】:

背景

让我们想象一个分布式系统,在微服务架构上,并行处理队列消息。本系统有两种应用:AB

A 是一个获取处理请求的 REST API 应用程序。每个请求都被转换为解决该请求的子任务列表。所以,一旦A收到一个新的请求,它就会在B应用的队列中插入N条消息。 N 是一个动态值,它是每个输入请求的变化。 一旦处理完成(所有N个项目都处理成功),我们将通知客户(请求者)总结果。

可能的解决方案

假设一个请求有 N 个子任务要处理。我们的应用程序A 将创建一个初始化值为 N 的原子计数器。应用程序B 每次处理来自队列的消息时,都会将计数器减 1 并查看其新值。

最后一次处理将在计数器上留下值“0”。一旦应用程序检测到值“0”,应用程序B 将通知客户处理结果。

问题

上述可能的解决方案有两个主要缺点:

  1. 您必须有一个可以同步所有常规进度的原子计数器。没有它,您将无法知道任务何时完成。
  2. 许多分布式队列系统,如 Google PubSub,采用“至少一次”传递 (source) 的方法,这意味着同一消息可以从队列中多次出列。这最终将导致在处理所有队列消息之前通知客户。

问题

当使用像 Google PubSub 这样的队列系统时,解决上述问题的正确方法是什么?

【问题讨论】:

  • 队列对于此类用例来说是错误的抽象。看看像 temporal.io 这样的编排器,它为动态任务协调提供直接支持。

标签: architecture microservices distributed-computing google-cloud-pubsub


【解决方案1】:

很高兴看到 Lauren 和 Cosmin 提供的不同观点。我认为他们已经提供了两个很好的方法,还有更多细节需要解决。

为了详细说明正确的解决方案,该问题未提供有关如何部署微服务以及高可用性要求的信息。

我们设计的一个类似的解决方案是使用持久存储来跟踪任务的进度(我们使用数据库)。它将有助于解耦每个任务的处理,并提供将每个任务分配给部署微服务 B 的集群中的不同节点的灵活性。使用持久存储来跟踪任务执行的状态(GCS Buckets 或 DB)将提供处理失败的弹性。如果一个节点在处理任务时出现故障,另一个节点可以通过使用 Pubsub 重新传递来接机。

我们应该检查DB或GCP存储桶中每个任务的执行状态,以便向客户发送最终通知(当所有任务完成时)。

【讨论】:

    【解决方案2】:

    你可以用Cloud Pub/Sub ordering keys来实现这种处理。然而,解决方案有点复杂,因为正如其他评论者所指出的,队列可能不是这种任务协调的最佳抽象。 Cloud TasksDataflow 或通过某种形式的存储整合工作可能更适合此用例。

    使用 Cloud Pub/Sub 执行此操作的一种方法是让 A 在单个区域中使用单个排序键发布其 N 消息,然后在同一排序键上发布“工作完成”消息。 Cloud Pub/Sub 将确保这些消息按顺序到达BB 不需要维护它处理了多少消息的计数器;一旦收到“工作完成”消息,它就知道可以通知客户处理结果。

    这将确保B 在所有子任务完成之前不会通知客户处理已完成。但是请注意,由于 Cloud Pub/Sub 的至少一次消息传递保证,B 仍然有可能多次通知客户相同的工作,除非您在 B 中执行一些重复数据删除。

    【讨论】:

      【解决方案3】:

      不使用原子计数器,应用程序B 不能简单地将消息放在另一个task completion queue 上,应用程序A 消费?那么只有应用程序A 会跟踪进度吗?

      关于您的问题,您可以用来解决该问题的一种方法是在数据库表中跟踪已完成的作业。一旦作业完成(所有 N 个任务都已处理),您将通知发送给客户端,但您也在数据库中标记作业已完成。

      然后,如果您将作为已完成作业的一部分的消息出列,则可以忽略它。

      【讨论】:

      • 1.可以让A(甚至是新玩家C)跟踪进度——但这需要更多资源。此外,原子计数器是强制性的。除非您定义只有一个应用程序实例正在关闭进度,否则您将失去 HA 和扩展能力。 2.忽略进入负区域的计数器导致在进度完成之前通知客户(因此,您没有完整的通知答案)。
      猜你喜欢
      • 2017-04-25
      • 2019-12-18
      • 2019-09-05
      • 2015-06-30
      • 2016-11-24
      • 2017-09-21
      • 1970-01-01
      • 2015-07-18
      • 2016-12-13
      相关资源
      最近更新 更多