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 端点,您的应用程序可以将此记录为一个结束呼叫,并继续为请求提供服务。