【问题标题】:Microservices: how to track fallen down services?微服务:如何追踪失败的服务?
【发布时间】:2020-07-28 07:24:34
【问题描述】:

问题: 假设有两个服务 A 和 B。服务 A 对服务 B 进行 API 调用。 一段时间后,服务 A 因网络错误而掉线或丢失。

其他服务如何猜测来自服务 A 的出站呼叫丢失/永远不会发生?我需要另一个并发应用程序,如果服务 A 出站呼叫丢失,它将自动做出反应(运行紧急代码)。

存在哪些前沿解决方案?

我的想法,例如:

  1. 服务 A 在某些中间件中注册调用事件(事件信息、“运行”状态、时间戳等)。
  2. 如果此调用在 N 秒后仍未完成,则中间件中的某些“调用超时”事件会自动启动紧急代码。
  3. 如果呼叫在适当的时间完成,服务 A 在同一中间件中将呼叫状态标记为“已完成”,紧急代码将不会运行。

附:我在 Java 堆栈上。

谢谢!

【问题讨论】:

    标签: microservices middleware distributed-computing soa fault-tolerance


    【解决方案1】:

    我建议研究诸如 RetryTimeoutCircuit BreakerFallback 等模式>健康检查。或者,如果您关心并发调用和故障隔离,您也可以查看 Bulkhead 模式。 有许多资源解释了这些众所周知的模式,例如:

    我不知道您使用的是哪个技术堆栈,但通常已经提供了一些针对这些问题的功能,您可以将这些功能整合到您的解决方案中。有些库已经处理了这种弹性功能,例如,您可以对其进行设置,以便在发生重试失败、超时、激活的断路器等事件时执行您的自定义代码。

    例如对于 Java 堆栈 Hystrix 被广泛使用,对于 .Net,您可以查看 Polly .Net 以利用重试、超时、断路器、隔板或回退功能.

    关于健康检查,您可以查看 Actuator for Java 和 .Net 核心已经提供了 health check middleware,它或多或少地提供了开箱即用的功能。

    但在使用任何库之前,我建议先熟悉所列模式的目的和概念,以选择和集成最适合您的用例和主要关注点的模式。

    更新

    我们必须在这里区分两个众所周知的问题:

    1.) 服务 A 如何稳健地处理服务 B 的临时中断(或服务 A 和 B 之间的网络连接归结为同样的问题)?

    为了解决相关问题,上述模式将有所帮助。

    2.) 如果服务A本身宕机,如何确保应该发送给服务B的请求不会丢失

    要解决这类问题,手头有不同的选择。

    2a.) 对服务 A 执行请求(然后触发服务 B)的组件也应用上述弹性模式,并将重试其请求,直到服务 A 成功回答它已执行其任务(这也包括成功请求服务 B)。

    每个服务也可以有多个实例,并且在这些实例前面有某种负载均衡器,它将请求分发并定向到特定服务的可用实例(基于定期执行的运行状况检查)。或者您可以使用服务注册表(请参阅https://microservices.io/patterns/service-registry.html)。

    您当然可以一个接一个地链接多个 API 调用,但这可能会导致级联故障。所以我宁愿采用异步通信方法,如下一个选项中所述。

    2b.) 让我们考虑一下,服务 A 的某个实例能够可靠地执行对服务 B 的请求是至关重要的。

    在这种情况下,您可以使用 消息队列,如下所示:

    • 假设您有一个队列,其中收集了要由服务 A 执行的作业。
    • 然后,您有多个正在运行的服务 A 实例(请参阅水平扩展),其中每个实例将使用相同的队列。
    • 您将使用消息队列服务的消息锁定 功能,以确保服务 A 的一个实例从队列中读取消息后,其他实例将看不到它。如果服务 A 能够完成它的工作(即调用服务 B,在服务 A 的持久性中保存一些状态以及成功处理需要包含的任何其他任务),它将从队列中删除消息之后 所以没有其他服务 A 实例也将处理相同的消息。
    • 如果服务 A 在处理过程中出现故障,队列服务将自动为您解锁消息,并且服务 A 的另一个实例 A(或重新启动后的同一实例)将尝试从队列并尝试执行所有任务(调用服务 B 等)

    您可以组合多个队列,例如还可以异步向服务 B 发送消息,而不是直接对其执行某种 API 调用。

    关键是,队列服务是一些高度可用和冗余的服务,它已经确保一旦发布到队列就不会丢失任何消息。

    当然,您也可以处理要在您自己的服务 A 数据库中执行的作业,但要考虑到当服务 A 收到请求时,总是有机会在它之前停止运行可以将作业的状态保存到其持久存储以供以后处理。如果经过深思熟虑并正确使用,队列服务已经为您解决了这个问题。

    例如,如果将 Kafka 视为消息传递服务,您可以查看此堆栈溢出答案,该答案与使用此特定技术时的问题解决方案有关:https://stackoverflow.com/a/44589842/7730554

    【讨论】:

    • 谢谢!我在Java堆栈上。如果我正确理解 Hystrix 是本地库,并且如果服务 A 关闭/丢失,那么它的 Hystrix 功能以及执行器都会关闭/丢失。其他服务如何猜测来自服务 A 的出站呼叫丢失?我需要另一个并发应用程序,如果服务 A 出站呼叫丢失,而不是整个服务 A,它将自动做出反应(运行紧急代码)。永久健康检查?它看起来不平凡......
    • 一开始我可能没有完全理解你的问题。我认为您需要在这里解决两个问题:第一个是确保 从服务 A 到服务 B 的请求在 服务 B 关闭时不会丢失 .在这里,您应该应用重试、超时、断路器、回退等模式,以便服务 A 可以对服务 B 的临时中断做出稳健的反应。
    • 您提到的另一个问题是服务 A 本身出现故障,并且应该执行的对服务 B 的请求永远不会发生?那正确吗?如果是这样,我也会相应地更新我的答案以解决这个问题。
    • 是的,你是对的。第一点(服务 B 已关闭)对我不感兴趣。可以通过 Hystrix 解决。但第二点(对服务 A 的请求永远不会发生)是我回答的主题。
    • 我更新了我的答案,也通过一些建议解决了这个问题。我还保留了最初的答案,因为我认为也有必要解决其他问题。
    【解决方案2】:

    有很多方法可以解决您的问题。

    我猜你在谈论微服务中的设计模式和 Cicruit Breaker 中的 2 个主题

    https://dzone.com/articles/design-patterns-for-microservices

    为了解决您的问题,通常我会在服务之间放置一个消息队列并使用服务发现来检测哪个服务处于活动状态,如果您的服务死亡或加载,则使用 Cicruit Breaker 方法

    【讨论】:

      猜你喜欢
      • 2014-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-27
      • 1970-01-01
      • 2019-02-15
      • 2017-08-30
      • 2022-01-22
      相关资源
      最近更新 更多