健康检查应该调用其他应用程序的健康检查吗?

22

我有两个API:A和B,我可以控制这两个API,并且两个API都有可读性和可用性的健康检查。 A依赖于B。


A
/foo - This endpoint makes a call to /bar in B
/status/live
/status/ready

B
/bar
/status/live
/status/ready

由于依赖关系,A的就绪健康检查是否应调用API B的就绪健康检查?

5个回答

17

如果Service A能够处理业务请求,那么它就已经准备好了。所以,如果能够到达B是其需要完成的一部分(看起来确实是这样),那么它应该检查B。

让A检查B的一个优点是你可以在错误的滚动升级时快速失败。假设A被错误配置,以至于升级功能包含了B的错误连接细节 - 可能B的服务名称被注入为环境变量,而新版本有一个拼写错误。如果A实例在启动时检查B,那么你可以更容易地确保升级失败,并且没有流量进入新的错误配置Pods。有关更多信息,请参见https://medium.com/spire-labs/utilizing-kubernetes-liveness-and-readiness-probes-to-automatically-recover-from-failure-2fe0314f2b2e

通常情况下,A只需要检查B的存活性端点或任何最小可用性端点,而不是B的准备就绪端点。这是因为Kubernetes将会为您检查B的准备就绪探针,因此A可以访问的任何B实例都将是就绪状态。如果B的准备就绪端点执行的检查比存活性端点多,则调用B的存活性端点而不是准备就绪可能会有所区别。请记住,Kubernetes将定期调用这些探针 - 准备就绪和存活性 - 它们都有一个周期。区别在于Pod是否从服务流量中撤出(如果准备就绪失败)或重新启动(如果存活性失败)。您不是在尝试进行端到端事务检查,您希望这些检查包含最少的逻辑并且不使用太多负载。
最好的方法是在A的准备就绪实现内部进行检查,而不是在k8s级别(在Pod规范本身中)进行检查。其次最好的方法是在k8s级别进行检查,因为理想情况下,您希望知道运行在容器中的代码确实连接了。
另一种检查依赖服务是否可用的方法是使用initContainer进行检查。使用initContainers可以避免在启动期间看到多次重启(通过确保正确的顺序),但通过探针对依赖项进行检查可以更深入(如果在应用程序代码中实现),并且这些探针将在启动后定期运行。因此,同时使用两者可能是有利的。
要小心不要过于自由地从就绪性检查其他服务,因为这可能导致级联不可用性。例如,如果后端暂时关闭并且前端正在探测它,则前端也将变为不可用状态,因此将无法显示良好的错误消息。您可能希望从简单的探测开始,并在逐步添加复杂性时小心谨慎。

如果B是Kubernetes之外的服务,那么情况就不同了,因为Kubernetes无法管理B的可用性。这时你可能需要让A实例存储请求或显示特定消息,而不是让Kubernetes停止发送流量到该A实例。 - Ryan Dawson

8
参考微软的 实现韧性应用 教程,具体来说是关于健康监控。建议如果当前服务的整体状态取决于一个依赖项的状态,则只有当其依赖项健康时,该服务的健康状态才应为健康。
然而,eShopOnContainers 的 MVC web 应用程序依赖于其他多个微服务。因此,它为每个微服务调用一个 AddUrlCheck 方法,如下例所示:
// Startup.cs from the MVC web app
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
        services.Configure<AppSettings>(Configuration);
        services.AddHealthChecks(checks =>
        {
            checks.AddUrlCheck(Configuration["CatalogUrl"]);
            checks.AddUrlCheck(Configuration["OrderingUrl"]);
            checks.AddUrlCheck(Configuration["BasketUrl"]);
            checks.AddUrlCheck(Configuration["IdentityUrl"]);
        });
    }
}

因此,只有当微服务的所有检查项都健康时,它才会提供“健康”的状态。

强调是我的

因此,更直接地回答你关于

由于依赖关系,A 的可读性健康检查是否应该调用 API B 的可读性健康检查?

我想说是的。特别是如果依赖关系 B 的健康状况直接影响到 A 的稳定性。


我们正在为我们的应用程序添加健康检查,并遇到了这个问题,偶然发现了这个问题,我所称之为:我们有一系列的应用程序,每个应用程序都在执行其任务,但也依赖于下一个应用程序。这意味着检查第一个应用程序的健康状况,实际上就是检查整个系统的健康状况。这样做是否明智?您是否希望这样做? - SvenL
@SvenL 是的,这基本上是你想要的。你间接地检查依赖项的健康状况,因为它们直接影响根应用程序。 - Nkosi

3

有准备和活性。我认为没有明显的答案,只有一个指导方针。
“Alive”表示服务仅仅是响应的,例如能够回复200 / OK的消息。
“Ready”表示服务正在按照预期工作。(最常用的API)

举个例子,在启动阶段,由于依赖组件/服务尚未准备好或处于运行状态,因此服务可能已经处于“alive”状态,但尚未准备就绪(例如DB尚未连接)。
因此,我会说,对于“ready”状态,您可能需要确保其他必要组件也处于“alive”或“ready”状态。 您需要决定的只是哪些是检查准备就绪的必要组件。


1
当我在一个应用程序中实现健康端点时,我会遵循最佳实践,检查应用程序需要工作的所有依赖项。
如果其中一个依赖项不工作,我的应用程序就无法工作,因此被标记为不健康。

0

不需要在其他微服务上检查健康状况。单个微服务应该可以独立工作(根据微服务定义)。如果一个微服务依赖于另一个微服务,则可以使用fallback、断路器模式来对抗其他微服务,以使其在不失败的情况下工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接