【问题标题】:Should Health Checks call other App Health Checks健康检查是否应该调用其他应用健康检查
【发布时间】:2018-12-20 17:06:23
【问题描述】:

我有两个由我控制的 API A 和 B,并且都进行了就绪性和活动性健康检查。 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 的就绪健康检查?

【问题讨论】:

    标签: url kubernetes api-design health-monitoring kubernetes-health-check


    【解决方案1】:

    如果服务 A 可以处理业务请求,则它已准备就绪。因此,如果能够到达 B 是它 需要 做的事情的一部分(看起来确实如此),那么它应该检查 B。

    让 A 检查 B 的好处是您可以 fail fast on a bad rolling upgrade。假设您的 A 配置错误,因此升级为 B 提供了错误的连接详细信息 - 可能 B 的服务名称作为环境变量注入,并且新版本有错字。如果您的 A 实例在启动时检查到 Bs,那么您可以更轻松地确保升级失败并且没有流量流向新配置错误的 Pod。有关更多信息,请参阅https://medium.com/spire-labs/utilizing-kubernetes-liveness-and-readiness-probes-to-automatically-recover-from-failure-2fe0314f2b2e

    A 检查 B 的活动端点或任何最小可用性端点而不是 B 的就绪端点通常就足够了。这是因为 kubernetes 将是 checking B's readiness probe for you anyway,因此 A 可以访问的任何 B 实例都将是一个就绪实例。如果 B 的readiness endpoint performs more checks than the liveness one,调用 B 的活动端点而不是准备状态可能会有所不同。请记住,kubernetes 将定期调用这些探测器 - readiness as well as liveness - they both have a period。区别在于 Pod 是退出服务流量(如果准备失败)还是重新启动(如果活动失败)。您不是在尝试执行 end-to-end transaction checks,而是希望这些检查包含最少的逻辑并且不会消耗过多的负载。

    如果 A 的 readiness 实现中的代码进行检查而不是在 k8s 级别(在 Pod 规范本身中)进行检查,则更好。最好在 k8s 级别执行此操作,因为理想情况下您想知道在容器中运行的代码确实可以连接。

    检查依赖服务的另一种方法是is with a check in an initContainer。使用 initContainers 可以避免在启动期间看到多次重启(通过确保正确的顺序),但是通过探针对依赖项进行检查可以更深入(如果在应用程序的代码中实现)并且探针将在启动后继续定期运行。因此,两者都使用可能是有利的。

    小心检查其他服务是否准备就绪,因为这会导致级联不可用。例如,如果一个后端短暂地出现故障并且前端正在对其进行探测,那么前端也将变得不可用,因此将无法显示良好的错误消息。您可能希望从简单的探测开始,然后小心地增加复杂性。

    【讨论】:

    • 如果 B 是 Kubernetes 之外的服务,那么这会改变事情,因为 k8s 无法管理 B 的可用性。然后,您可能希望 A 实例存储请求或显示特定消息,而不是让 k8s 停止向该 A 实例发送流量。
    【解决方案2】:

    参考微软的Implementing Resilient Applications 教程。特别是Health monitoring,建议如果当前服务的整体状态依赖于依赖的状态,那么服务的健康状态应该只有在其依赖健康的情况下才是健康的

    但是,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的稳定性。

    【讨论】:

      【解决方案3】:

      有准备和活跃。而且我认为没有明显的答案。只是一个准则 -
      活着意味着服务只是响应式的。例如能够以 200/OK 响应。 就绪意味着按预期工作。 (这是最常用的 API)

      例如,在启动阶段,服务可能还没有准备好,因为依赖的组件/服务还没有活动或准备好。 (例如,尚未连接数据库)。 因此,我会说是的,为了准备就绪,您可能需要确保其他基本组件处于活动状态或也准备就绪。您所要做的就是决定哪些是要检查准备情况的必需品。

      【讨论】:

        【解决方案4】:

        当我在一个应用程序中实现运行状况端点时,我会遵循最佳实践来检查应用程序运行所需的所有依赖项。

        如果这些依赖项之一不起作用,我的应用程序将无法运行,因此它被标记为不健康。

        【讨论】:

          【解决方案5】:

          不,您不需要在其他微服务上检查 healthchek。无论其他微服务如何(根据微服务定义),单个微服务都应该工作。如果一个微服务依赖于另一个微服务,那么您可以对其他微服务使用 fallBack、断路器模式,这样它就可以正常工作而不会失败。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-10-02
            • 2021-09-13
            • 2019-11-03
            • 1970-01-01
            • 1970-01-01
            • 2021-04-20
            • 1970-01-01
            • 2017-07-16
            相关资源
            最近更新 更多