18.3.3 应用存活性和就绪性

正如我们在第 15 章中所看到的, Actuator 的 health 端点提供了一个系统的健康状态。但这种健康状况只与应用程序依赖的下层组件有关,例如数据库或消息代理。即使应用程序是完全健康的,但数据库连接不正常,这并不意味着它已经准备好处理请求了,或者确保可以在当前状态下继续运行。

Kubernetes 支持存活性和就绪性探测的概念:应用程序的健康探测器帮助 Kubernetes 确定是否应将流量发送到应用程序上,或应用程序是否应该重新启动以解决某些问题。Spring Boot 支持存活性和就绪性探测,通过 Actuator health 端点的子集(称为 health groups)。

存活性是应用程序是否健康,以便可以继续运行,而无需重新启动的指标。如果应用程序指示其存活性为 DOWN,则 Kubernetes 运行时可以通过终止应用程序正在运行的 pod,并启动新的取而代之。

另一方面,就绪性告诉 Kubernetes 应用程序是否准备好处理请求。例如,启动时应用程序开始处理请求之前,可能需要执行一些初始化。在此期间,应用程序的就绪状态可能会显示 Down,而应用程序一直处于存活状态,因此 Kubernetes 不会重新启动它。一旦应用程序已完成初始化,它可以设置就绪探测器为 UP,以指示它已启动,Kubernetes 将把请求转到到应用上。

启用存活性和就绪性探测器

为了在 Spring Boot 应用程序中启用存活性和就绪性探测器,需要设置 management.health.probes.enabled 为 true,在 application.yml 文件中像这样设置:

management:
  health:
    probes:
      enabled: true

启用探测器后,对 Actuator health 端点的请求将返回类似如下的数据(假设应用程序完全健康):

{
  "status": "UP",
  "groups": [
    "liveness",
    "readiness"
  ]
}

就其本身而言,基本 health 端点并没有告诉我们,一个项目的存活性和就绪性的太多信息。但对 /actuator/health/liveness/actuator/health/readiness 的请求,将提供应用程序存活性和就绪性状态。在任何一种情况下,“UP”状态会像这样:

{
  "status": "UP"
}

另一方面,如果存活性和就绪性为 DOWN,则返回结果如下所示:

{
  "status": "DOWN"
}

在就绪性为“DOWN”状态下,Kubernetes 不会将请求转发到应用程序。如果存活性探测器指示“DOWN”状态,Kubernetes 将通过删除 pod 并在其他位置启动新实例来解决此问题。

在部署中配置存活性和就绪性探测器

随着 Actuator 在这两个端点上产生存活性和就绪性状态,我们需要做的就是在部署清单中告诉Kubernetes 有关它们的信息。以下部署清单内容在结尾处显示了让 Kubernetes 知道如何检查存活性和就绪性:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: taco-cloud-deploy
  labels:
    app: taco-cloud
spec:
  replicas: 3
  selector:
    matchLabels:
      app: taco-cloud
  template:
    metadata:
      labels:
        app: taco-cloud
    spec:
      containers:
      - name: taco-cloud-container
        image: tacocloud/tacocloud:latest
        livenessProbe:
          initialDelaySeconds: 2
          periodSeconds: 5
          httpGet:
            path: /actuator/health/liveness
            port: 8080
        readinessProbe:
          initialDelaySeconds: 2
          periodSeconds: 5
          httpGet:
            path: /actuator/health/readiness
            port: 8080

这告诉 Kubernetes,对于每个探测器,都要向端口 8080 上的给定路径发出 GET 请求获得存活性和就绪性状态。按照这里的配置,第一个请求应该发生在应用程序 pod 运行后的 2 秒后,此后每 5 秒一次。

管理存活性和就绪性

那么,是如何设置存活性和就绪性状态的呢?在内部,Spring 本身或应用程序所依赖的某个库组件,可以通过发布可用性更改事件来设置状态。但这种能力并不局限于 Spring 及其相关库,您还可以在应用程序中编写代码发布这些事件。

例如,假设您希望将应用程序的就绪性延迟到某些初始化之后。在应用程序生命周期的早期,在 ApplicationRunner 或 CommandLineRunner bean 中,您可以发布就绪性状态以拒绝处理请求:

@Bean
public ApplicationRunner disableLiveness(ApplicationContext context) {
  return args -> {
    AvailabilityChangeEvent.publish(context, ReadinessState.REFUSING_TRAFFIC);
  };
}

这里,ApplicationRunner 被提供一个 Spring 应用程序上下文的实例,作为 @Bean 方法的参数。这是必需的,因为静态 publish() 方法需要它来发布事件。

初始化完成后,可以更新应用程序的就绪性状态以接受流量,类似这样:

AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC);

存活性状态可以以非常相同的方式更新。关键的区别在于不是发布 ReadinessState.ACCEPTING_TRAFFIC 或 ReadinessState.REFUSING_TRAFFIC,而是发布 LivenessState.CORRECT 或 LivenessState.BROKEN。

例如,如果在应用程序代码中检测到不可恢复的致命错误,则应用程序可以通过发布 LivenessState.BROKEN 请求终止并重新启动它,如下所示:

AvailabilityChangeEvent.publish(context, LivenessState.BROKEN);

此事件发布后不久,liveness 端点将指示应用程序状态为 DOWN。Kubernetes 将采取重新启动应用程序的行动。这留给您发布 LivenessState.CORRECT 事件的时间很短。但是,如果您确定,应用程序是健康的,然后您可以通过发布新事件撤消以前的事件, 像这样:

AvailabilityChangeEvent.publish(context, LivenessState.CORRECT);

只要 Kubernetes 在您将状态设置为“DOWN”后还没有请求 liveness 端点,您的应用程序可以将此记录为一个结束呼叫,并继续为请求提供服务。

results matching ""

    No results matching ""